aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/breakpad/src/common/linux
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libs/breakpad/src/common/linux')
-rw-r--r--contrib/libs/breakpad/src/common/linux/breakpad_getcontext.S552
-rw-r--r--contrib/libs/breakpad/src/common/linux/breakpad_getcontext.h56
-rw-r--r--contrib/libs/breakpad/src/common/linux/crc32.cc70
-rw-r--r--contrib/libs/breakpad/src/common/linux/crc32.h53
-rw-r--r--contrib/libs/breakpad/src/common/linux/dump_symbols.cc1148
-rw-r--r--contrib/libs/breakpad/src/common/linux/dump_symbols.h93
-rw-r--r--contrib/libs/breakpad/src/common/linux/eintr_wrapper.h58
-rw-r--r--contrib/libs/breakpad/src/common/linux/elf_core_dump.cc203
-rw-r--r--contrib/libs/breakpad/src/common/linux/elf_core_dump.h157
-rw-r--r--contrib/libs/breakpad/src/common/linux/elf_gnu_compat.h51
-rw-r--r--contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.cc178
-rw-r--r--contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.h58
-rw-r--r--contrib/libs/breakpad/src/common/linux/elfutils-inl.h74
-rw-r--r--contrib/libs/breakpad/src/common/linux/elfutils.cc243
-rw-r--r--contrib/libs/breakpad/src/common/linux/elfutils.h135
-rw-r--r--contrib/libs/breakpad/src/common/linux/file_id.cc203
-rw-r--r--contrib/libs/breakpad/src/common/linux/file_id.h90
-rw-r--r--contrib/libs/breakpad/src/common/linux/guid_creator.cc189
-rw-r--r--contrib/libs/breakpad/src/common/linux/guid_creator.h48
-rw-r--r--contrib/libs/breakpad/src/common/linux/http_upload.cc230
-rw-r--r--contrib/libs/breakpad/src/common/linux/http_upload.h90
-rw-r--r--contrib/libs/breakpad/src/common/linux/ignore_ret.h40
-rw-r--r--contrib/libs/breakpad/src/common/linux/libcurl_wrapper.cc338
-rw-r--r--contrib/libs/breakpad/src/common/linux/libcurl_wrapper.h119
-rw-r--r--contrib/libs/breakpad/src/common/linux/linux_libc_support.cc237
-rw-r--r--contrib/libs/breakpad/src/common/linux/linux_libc_support.h96
-rw-r--r--contrib/libs/breakpad/src/common/linux/memory_mapped_file.cc108
-rw-r--r--contrib/libs/breakpad/src/common/linux/memory_mapped_file.h87
-rw-r--r--contrib/libs/breakpad/src/common/linux/safe_readlink.cc53
-rw-r--r--contrib/libs/breakpad/src/common/linux/safe_readlink.h65
-rw-r--r--contrib/libs/breakpad/src/common/linux/symbol_collector_client.cc195
-rw-r--r--contrib/libs/breakpad/src/common/linux/symbol_collector_client.h88
-rw-r--r--contrib/libs/breakpad/src/common/linux/symbol_upload.cc284
-rw-r--r--contrib/libs/breakpad/src/common/linux/symbol_upload.h76
-rw-r--r--contrib/libs/breakpad/src/common/linux/ucontext_constants.h153
35 files changed, 5918 insertions, 0 deletions
diff --git a/contrib/libs/breakpad/src/common/linux/breakpad_getcontext.S b/contrib/libs/breakpad/src/common/linux/breakpad_getcontext.S
new file mode 100644
index 0000000000..2ebcf31910
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/breakpad_getcontext.S
@@ -0,0 +1,552 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A minimalistic implementation of getcontext() to be used by
+// Google Breakpad when getcontext() is not available in libc.
+
+#include "common/linux/ucontext_constants.h"
+
+/* int getcontext (ucontext_t* ucp) */
+
+#if defined(__arm__)
+
+ .text
+ .global breakpad_getcontext
+ .hidden breakpad_getcontext
+ .type breakpad_getcontext, #function
+ .align 0
+ .fnstart
+breakpad_getcontext:
+
+ /* First, save r4-r11 */
+ add r1, r0, #(MCONTEXT_GREGS_OFFSET + 4*4)
+ stm r1, {r4-r11}
+
+ /* r12 is a scratch register, don't save it */
+
+ /* Save sp and lr explicitly. */
+ /* - sp can't be stored with stmia in Thumb-2 */
+ /* - STM instructions that store sp and pc are deprecated in ARM */
+ str sp, [r0, #(MCONTEXT_GREGS_OFFSET + 13*4)]
+ str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
+
+ /* Save the caller's address in 'pc' */
+ str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 15*4)]
+
+ /* Save ucontext_t* pointer across next call */
+ mov r4, r0
+
+ /* Call sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
+ mov r0, #0 /* SIG_BLOCK */
+ mov r1, #0 /* NULL */
+ add r2, r4, #UCONTEXT_SIGMASK_OFFSET
+ bl sigprocmask(PLT)
+
+ /* Intentionally do not save the FPU state here. This is because on
+ * Linux/ARM, one should instead use ptrace(PTRACE_GETFPREGS) or
+ * ptrace(PTRACE_GETVFPREGS) to get it.
+ *
+ * Note that a real implementation of getcontext() would need to save
+ * this here to allow setcontext()/swapcontext() to work correctly.
+ */
+
+ /* Restore the values of r4 and lr */
+ mov r0, r4
+ ldr lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
+ ldr r4, [r0, #(MCONTEXT_GREGS_OFFSET + 4*4)]
+
+ /* Return 0 */
+ mov r0, #0
+ bx lr
+
+ .fnend
+ .size breakpad_getcontext, . - breakpad_getcontext
+
+#elif defined(__aarch64__)
+
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT
+ // ENABLE_PAUTH must be defined to 1 since this value will be used in
+ // bitwise-shift later!
+ #define ENABLE_PAUTH 1
+
+ #if ((__ARM_FEATURE_PAC_DEFAULT&((1<<0)|(1<<1)))==0)
+ #error Pointer authentication defines no valid key!
+ #endif
+#else
+ #define ENABLE_PAUTH 0
+#endif
+
+#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT==1)
+ // ENABLE_BTI must be defined to 1 since this value will be used in
+ // bitwise-shift later!
+ #define ENABLE_BTI 1
+#else
+ #define ENABLE_BTI 0
+#endif
+
+
+// Although Pointer Authentication and Branch Target Instructions are technically
+// seperate features they work together, i.e. the paciasp and pacibsp instructions
+// serve as BTI landing pads.
+// Therefore PA-instructions are enabled when PA _or_ BTI is enabled!
+#if ENABLE_PAUTH || ENABLE_BTI
+ // See section "Pointer Authentication" of
+ // https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros
+ // for details how to interpret __ARM_FEATURE_PAC_DEFAULT
+ #if (__ARM_FEATURE_PAC_DEFAULT & (1<<0))
+ #define PAUTH_SIGN_SP paciasp
+ #define PAUTH_AUTH_SP autiasp
+ #else
+ #define PAUTH_SIGN_SP pacibsp
+ #define PAUTH_AUTH_SP autibsp
+ #endif
+#else
+ #define PAUTH_SIGN_SP
+ #define PAUTH_AUTH_SP
+#endif
+
+#define _NSIG 64
+#define __NR_rt_sigprocmask 135
+
+ .text
+ .global breakpad_getcontext
+ .hidden breakpad_getcontext
+ .type breakpad_getcontext, #function
+ .align 4
+ .cfi_startproc
+breakpad_getcontext:
+
+ PAUTH_SIGN_SP
+
+ /* The saved context will return to the getcontext() call point
+ with a return value of 0 */
+ str xzr, [x0, MCONTEXT_GREGS_OFFSET + 0 * REGISTER_SIZE]
+
+ stp x18, x19, [x0, MCONTEXT_GREGS_OFFSET + 18 * REGISTER_SIZE]
+ stp x20, x21, [x0, MCONTEXT_GREGS_OFFSET + 20 * REGISTER_SIZE]
+ stp x22, x23, [x0, MCONTEXT_GREGS_OFFSET + 22 * REGISTER_SIZE]
+ stp x24, x25, [x0, MCONTEXT_GREGS_OFFSET + 24 * REGISTER_SIZE]
+ stp x26, x27, [x0, MCONTEXT_GREGS_OFFSET + 26 * REGISTER_SIZE]
+ stp x28, x29, [x0, MCONTEXT_GREGS_OFFSET + 28 * REGISTER_SIZE]
+ str x30, [x0, MCONTEXT_GREGS_OFFSET + 30 * REGISTER_SIZE]
+
+ /* Place LR into the saved PC, this will ensure that when
+ switching to this saved context with setcontext() control
+ will pass back to the caller of getcontext(), we have
+ already arranged to return the appropriate return value in x0
+ above. */
+ str x30, [x0, MCONTEXT_PC_OFFSET]
+
+ /* Save the current SP */
+ mov x2, sp
+ str x2, [x0, MCONTEXT_SP_OFFSET]
+
+ /* Initialize the pstate. */
+ str xzr, [x0, MCONTEXT_PSTATE_OFFSET]
+
+ /* Figure out where to place the first context extension
+ block. */
+ add x2, x0, #MCONTEXT_EXTENSION_OFFSET
+
+ /* Write the context extension fpsimd header. */
+ mov w3, #(FPSIMD_MAGIC & 0xffff)
+ movk w3, #(FPSIMD_MAGIC >> 16), lsl #16
+ str w3, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
+ mov w3, #FPSIMD_CONTEXT_SIZE
+ str w3, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
+
+ /* Fill in the FP SIMD context. */
+ add x3, x2, #(FPSIMD_CONTEXT_VREGS_OFFSET + 8 * SIMD_REGISTER_SIZE)
+ stp d8, d9, [x3], #(2 * SIMD_REGISTER_SIZE)
+ stp d10, d11, [x3], #(2 * SIMD_REGISTER_SIZE)
+ stp d12, d13, [x3], #(2 * SIMD_REGISTER_SIZE)
+ stp d14, d15, [x3], #(2 * SIMD_REGISTER_SIZE)
+
+ add x3, x2, FPSIMD_CONTEXT_FPSR_OFFSET
+
+ mrs x4, fpsr
+ str w4, [x3]
+
+ mrs x4, fpcr
+ str w4, [x3, FPSIMD_CONTEXT_FPCR_OFFSET - FPSIMD_CONTEXT_FPSR_OFFSET]
+
+ /* Write the termination context extension header. */
+ add x2, x2, #FPSIMD_CONTEXT_SIZE
+
+ str xzr, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
+ str xzr, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
+
+ /* Grab the signal mask */
+ /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+ add x2, x0, #UCONTEXT_SIGMASK_OFFSET
+ mov x0, #0 /* SIG_BLOCK */
+ mov x1, #0 /* NULL */
+ mov x3, #(_NSIG / 8)
+ mov x8, #__NR_rt_sigprocmask
+ svc 0
+
+ /* Return x0 for success */
+ mov x0, 0
+
+ PAUTH_AUTH_SP
+
+ ret
+
+ .cfi_endproc
+ .size breakpad_getcontext, . - breakpad_getcontext
+
+#elif defined(__i386__)
+
+ .text
+ .global breakpad_getcontext
+ .hidden breakpad_getcontext
+ .align 4
+ .type breakpad_getcontext, @function
+
+breakpad_getcontext:
+
+ movl 4(%esp), %eax /* eax = uc */
+
+ /* Save register values */
+ movl %ecx, MCONTEXT_ECX_OFFSET(%eax)
+ movl %edx, MCONTEXT_EDX_OFFSET(%eax)
+ movl %ebx, MCONTEXT_EBX_OFFSET(%eax)
+ movl %edi, MCONTEXT_EDI_OFFSET(%eax)
+ movl %esi, MCONTEXT_ESI_OFFSET(%eax)
+ movl %ebp, MCONTEXT_EBP_OFFSET(%eax)
+
+ movl (%esp), %edx /* return address */
+ lea 4(%esp), %ecx /* exclude return address from stack */
+ mov %edx, MCONTEXT_EIP_OFFSET(%eax)
+ mov %ecx, MCONTEXT_ESP_OFFSET(%eax)
+
+ xorl %ecx, %ecx
+ movw %fs, %cx
+ mov %ecx, MCONTEXT_FS_OFFSET(%eax)
+
+ movl $0, MCONTEXT_EAX_OFFSET(%eax)
+
+ /* Save floating point state to fpregstate, then update
+ * the fpregs pointer to point to it */
+ leal UCONTEXT_FPREGS_MEM_OFFSET(%eax), %ecx
+ fnstenv (%ecx)
+ fldenv (%ecx)
+ mov %ecx, UCONTEXT_FPREGS_OFFSET(%eax)
+
+ /* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
+ leal UCONTEXT_SIGMASK_OFFSET(%eax), %edx
+ xorl %ecx, %ecx
+ push %edx /* &uc->uc_sigmask */
+ push %ecx /* NULL */
+ push %ecx /* SIGBLOCK == 0 on i386 */
+ call sigprocmask@PLT
+ addl $12, %esp
+
+ movl $0, %eax
+ ret
+
+ .size breakpad_getcontext, . - breakpad_getcontext
+
+#elif defined(__mips__)
+
+// This implementation is inspired by implementation of getcontext in glibc.
+#include <asm-mips/asm.h>
+#include <asm-mips/regdef.h>
+#if _MIPS_SIM == _ABIO32
+#include <asm-mips/fpregdef.h>
+#endif
+
+// from asm-mips/asm.h
+#if _MIPS_SIM == _ABIO32
+#define ALSZ 7
+#define ALMASK ~7
+#define SZREG 4
+#else // _MIPS_SIM != _ABIO32
+#define ALSZ 15
+#define ALMASK ~15
+#define SZREG 8
+#endif
+
+#include <asm/unistd.h> // for __NR_rt_sigprocmask
+
+#define _NSIG8 128 / 8
+#define SIG_BLOCK 1
+
+
+ .text
+LOCALS_NUM = 1 // save gp on stack
+FRAME_SIZE = ((LOCALS_NUM * SZREG) + ALSZ) & ALMASK
+
+GP_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG)
+MCONTEXT_REG_SIZE = 8
+
+#if _MIPS_SIM == _ABIO32
+
+NESTED (breakpad_getcontext, FRAME_SIZE, ra)
+ .mask 0x00000000, 0
+ .fmask 0x00000000, 0
+
+ .set noreorder
+ .cpload t9
+ .set reorder
+
+ move a2, sp
+#define _SP a2
+
+ addiu sp, -FRAME_SIZE
+ .cprestore GP_FRAME_OFFSET
+
+ sw s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw fp, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sw ra, MCONTEXT_PC_OFFSET(a0)
+
+#ifdef __mips_hard_float
+ s.d fs0, (20 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d fs1, (22 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d fs2, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d fs3, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d fs4, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d fs5, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+
+ cfc1 v1, fcr31
+ sw v1, MCONTEXT_FPC_CSR(a0)
+#endif // __mips_hard_float
+
+ /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+ li a3, _NSIG8
+ addu a2, a0, UCONTEXT_SIGMASK_OFFSET
+ move a1, zero
+ li a0, SIG_BLOCK
+ li v0, __NR_rt_sigprocmask
+ syscall
+
+ addiu sp, FRAME_SIZE
+ jr ra
+
+END (breakpad_getcontext)
+#else
+
+#ifndef NESTED
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define NESTED(symbol, framesize, rpc) \
+ .globl symbol; \
+ .align 2; \
+ .type symbol,@function; \
+ .ent symbol,0; \
+symbol: .frame sp, framesize, rpc;
+#endif
+
+/*
+ * END - mark end of function
+ */
+#ifndef END
+# define END(function) \
+ .end function; \
+ .size function,.-function
+#endif
+
+/* int getcontext (ucontext_t* ucp) */
+
+NESTED (breakpad_getcontext, FRAME_SIZE, ra)
+ .mask 0x10000000, 0
+ .fmask 0x00000000, 0
+
+ move a2, sp
+#define _SP a2
+ move a3, gp
+#define _GP a3
+
+ daddiu sp, -FRAME_SIZE
+ .cpsetup $25, GP_FRAME_OFFSET, breakpad_getcontext
+
+ /* Store a magic flag. */
+ li v1, 1
+ sd v1, (0 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) /* zero */
+
+ sd s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd _GP, (28 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd s8, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
+ sd ra, MCONTEXT_PC_OFFSET(a0)
+
+#ifdef __mips_hard_float
+ s.d $f24, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f25, (25 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f26, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f27, (27 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f28, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f29, (29 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f30, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+ s.d $f31, (31 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
+
+ cfc1 v1, $31
+ sw v1, MCONTEXT_FPC_CSR(a0)
+#endif /* __mips_hard_float */
+
+/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+ li a3, _NSIG8
+ daddu a2, a0, UCONTEXT_SIGMASK_OFFSET
+ move a1, zero
+ li a0, SIG_BLOCK
+
+ li v0, __NR_rt_sigprocmask
+ syscall
+
+ .cpreturn
+ daddiu sp, FRAME_SIZE
+ move v0, zero
+ jr ra
+
+END (breakpad_getcontext)
+#endif // _MIPS_SIM == _ABIO32
+
+#elif defined(__x86_64__)
+/* The x64 implementation of breakpad_getcontext was derived in part
+ from the implementation of libunwind which requires the following
+ notice. */
+/* libunwind - a platform-independent unwind library
+ Copyright (C) 2008 Google, Inc
+ Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
+ Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+
+This file is part of libunwind.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+
+ .text
+ .global breakpad_getcontext
+ .hidden breakpad_getcontext
+ .align 4
+ .type breakpad_getcontext, @function
+
+breakpad_getcontext:
+ .cfi_startproc
+
+ /* Callee saved: RBX, RBP, R12-R15 */
+ movq %r12, MCONTEXT_GREGS_R12(%rdi)
+ movq %r13, MCONTEXT_GREGS_R13(%rdi)
+ movq %r14, MCONTEXT_GREGS_R14(%rdi)
+ movq %r15, MCONTEXT_GREGS_R15(%rdi)
+ movq %rbp, MCONTEXT_GREGS_RBP(%rdi)
+ movq %rbx, MCONTEXT_GREGS_RBX(%rdi)
+
+ /* Save argument registers (not strictly needed, but setcontext
+ restores them, so don't restore garbage). */
+ movq %r8, MCONTEXT_GREGS_R8(%rdi)
+ movq %r9, MCONTEXT_GREGS_R9(%rdi)
+ movq %rdi, MCONTEXT_GREGS_RDI(%rdi)
+ movq %rsi, MCONTEXT_GREGS_RSI(%rdi)
+ movq %rdx, MCONTEXT_GREGS_RDX(%rdi)
+ movq %rax, MCONTEXT_GREGS_RAX(%rdi)
+ movq %rcx, MCONTEXT_GREGS_RCX(%rdi)
+
+ /* Save fp state (not needed, except for setcontext not
+ restoring garbage). */
+ leaq MCONTEXT_FPREGS_MEM(%rdi),%r8
+ movq %r8, MCONTEXT_FPREGS_PTR(%rdi)
+ fnstenv (%r8)
+ stmxcsr FPREGS_OFFSET_MXCSR(%r8)
+
+ leaq 8(%rsp), %rax /* exclude this call. */
+ movq %rax, MCONTEXT_GREGS_RSP(%rdi)
+
+ movq 0(%rsp), %rax
+ movq %rax, MCONTEXT_GREGS_RIP(%rdi)
+
+ /* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
+ leaq UCONTEXT_SIGMASK_OFFSET(%rdi), %rdx // arg3
+ xorq %rsi, %rsi // arg2 NULL
+ xorq %rdi, %rdi // arg1 SIGBLOCK == 0
+ call sigprocmask@PLT
+
+ /* Always return 0 for success, even if sigprocmask failed. */
+ xorl %eax, %eax
+ ret
+ .cfi_endproc
+ .size breakpad_getcontext, . - breakpad_getcontext
+
+#else
+#error "This file has not been ported for your CPU!"
+#endif
+
+#if defined(__aarch64__)
+// ENABLE_PAUTH and ENABLE_BTI would be enabled at the definition
+// of AArch64 specific breakpad_getcontext function
+#if ENABLE_PAUTH || ENABLE_BTI
+// for further information on the .note.gnu.property section see
+// https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#program-property
+.pushsection .note.gnu.property, "a";
+ .balign 8
+ .long 4
+ .long 0x10
+ .long 0x5
+ .asciz "GNU"
+ .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
+ .long 4
+ .long ((ENABLE_PAUTH)<<1) | ((ENABLE_BTI)<<0) /* PAuth and BTI */
+ .long 0
+.popsection
+#endif
+#endif
diff --git a/contrib/libs/breakpad/src/common/linux/breakpad_getcontext.h b/contrib/libs/breakpad/src/common/linux/breakpad_getcontext.h
new file mode 100644
index 0000000000..1418cde621
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/breakpad_getcontext.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
+#define GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_GETCONTEXT
+
+#include <signal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Provided by src/common/linux/breakpad_getcontext.S
+int breakpad_getcontext(ucontext_t* ucp);
+
+#define getcontext(x) breakpad_getcontext(x)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // HAVE_GETCONTEXT
+
+#endif // GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
diff --git a/contrib/libs/breakpad/src/common/linux/crc32.cc b/contrib/libs/breakpad/src/common/linux/crc32.cc
new file mode 100644
index 0000000000..8df636ce4d
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/crc32.cc
@@ -0,0 +1,70 @@
+// Copyright 2014 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/linux/crc32.h"
+
+namespace google_breakpad {
+
+// This implementation is based on the sample implementation in RFC 1952.
+
+// CRC32 polynomial, in reversed form.
+// See RFC 1952, or http://en.wikipedia.org/wiki/Cyclic_redundancy_check
+static const uint32_t kCrc32Polynomial = 0xEDB88320;
+static uint32_t kCrc32Table[256] = { 0 };
+
+#define arraysize(f) (sizeof(f) / sizeof(*f))
+
+static void EnsureCrc32TableInited() {
+ if (kCrc32Table[arraysize(kCrc32Table) - 1])
+ return; // already inited
+ for (uint32_t i = 0; i < arraysize(kCrc32Table); ++i) {
+ uint32_t c = i;
+ for (size_t j = 0; j < 8; ++j) {
+ if (c & 1) {
+ c = kCrc32Polynomial ^ (c >> 1);
+ } else {
+ c >>= 1;
+ }
+ }
+ kCrc32Table[i] = c;
+ }
+}
+
+uint32_t UpdateCrc32(uint32_t start, const void* buf, size_t len) {
+ EnsureCrc32TableInited();
+
+ uint32_t c = start ^ 0xFFFFFFFF;
+ const uint8_t* u = static_cast<const uint8_t*>(buf);
+ for (size_t i = 0; i < len; ++i) {
+ c = kCrc32Table[(c ^ u[i]) & 0xFF] ^ (c >> 8);
+ }
+ return c ^ 0xFFFFFFFF;
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/crc32.h b/contrib/libs/breakpad/src/common/linux/crc32.h
new file mode 100644
index 0000000000..e3d9db92be
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/crc32.h
@@ -0,0 +1,53 @@
+// Copyright 2014 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_CRC32_H_
+#define COMMON_LINUX_CRC32_H_
+
+#include <stdint.h>
+
+#include <string>
+
+namespace google_breakpad {
+
+// Updates a CRC32 checksum with |len| bytes from |buf|. |initial| holds the
+// checksum result from the previous update; for the first call, it should be 0.
+uint32_t UpdateCrc32(uint32_t initial, const void* buf, size_t len);
+
+// Computes a CRC32 checksum using |len| bytes from |buf|.
+inline uint32_t ComputeCrc32(const void* buf, size_t len) {
+ return UpdateCrc32(0, buf, len);
+}
+inline uint32_t ComputeCrc32(const std::string& str) {
+ return ComputeCrc32(str.c_str(), str.size());
+}
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_CRC32_H_
diff --git a/contrib/libs/breakpad/src/common/linux/dump_symbols.cc b/contrib/libs/breakpad/src/common/linux/dump_symbols.cc
new file mode 100644
index 0000000000..75a4ceed27
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/dump_symbols.cc
@@ -0,0 +1,1148 @@
+// Copyright (c) 2011 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Restructured in 2009 by: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
+
+// dump_symbols.cc: implement google_breakpad::WriteSymbolFile:
+// Find all the debugging info in a file and dump it as a Breakpad symbol file.
+
+#include "common/linux/dump_symbols.h"
+
+#include <assert.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <link.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "common/dwarf/bytereader-inl.h"
+#include "common/dwarf/dwarf2diehandler.h"
+#include "common/dwarf_cfi_to_module.h"
+#include "common/dwarf_cu_to_module.h"
+#include "common/dwarf_line_to_module.h"
+#include "common/dwarf_range_list_handler.h"
+#include "common/linux/crc32.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/elfutils.h"
+#include "common/linux/elfutils-inl.h"
+#include "common/linux/elf_symbols_to_module.h"
+#include "common/linux/file_id.h"
+#include "common/memory_allocator.h"
+#include "common/module.h"
+#include "common/path_helper.h"
+#include "common/scoped_ptr.h"
+#ifndef NO_STABS_SUPPORT
+#include "common/stabs_reader.h"
+#include "common/stabs_to_module.h"
+#endif
+#include "common/using_std_string.h"
+
+// This namespace contains helper functions.
+namespace {
+
+using google_breakpad::DumpOptions;
+using google_breakpad::DwarfCFIToModule;
+using google_breakpad::DwarfCUToModule;
+using google_breakpad::DwarfLineToModule;
+using google_breakpad::DwarfRangeListHandler;
+using google_breakpad::ElfClass;
+using google_breakpad::ElfClass32;
+using google_breakpad::ElfClass64;
+using google_breakpad::elf::FileID;
+using google_breakpad::FindElfSectionByName;
+using google_breakpad::GetOffset;
+using google_breakpad::IsValidElf;
+using google_breakpad::elf::kDefaultBuildIdSize;
+using google_breakpad::Module;
+using google_breakpad::PageAllocator;
+#ifndef NO_STABS_SUPPORT
+using google_breakpad::StabsToModule;
+#endif
+using google_breakpad::scoped_ptr;
+using google_breakpad::wasteful_vector;
+
+// Define AARCH64 ELF architecture if host machine does not include this define.
+#ifndef EM_AARCH64
+#define EM_AARCH64 183
+#endif
+
+//
+// FDWrapper
+//
+// Wrapper class to make sure opened file is closed.
+//
+class FDWrapper {
+ public:
+ explicit FDWrapper(int fd) :
+ fd_(fd) {}
+ ~FDWrapper() {
+ if (fd_ != -1)
+ close(fd_);
+ }
+ int get() {
+ return fd_;
+ }
+ int release() {
+ int fd = fd_;
+ fd_ = -1;
+ return fd;
+ }
+ private:
+ int fd_;
+};
+
+//
+// MmapWrapper
+//
+// Wrapper class to make sure mapped regions are unmapped.
+//
+class MmapWrapper {
+ public:
+ MmapWrapper() : is_set_(false) {}
+ ~MmapWrapper() {
+ if (is_set_ && base_ != NULL) {
+ assert(size_ > 0);
+ munmap(base_, size_);
+ }
+ }
+ void set(void* mapped_address, size_t mapped_size) {
+ is_set_ = true;
+ base_ = mapped_address;
+ size_ = mapped_size;
+ }
+ void release() {
+ assert(is_set_);
+ is_set_ = false;
+ base_ = NULL;
+ size_ = 0;
+ }
+
+ private:
+ bool is_set_;
+ void* base_;
+ size_t size_;
+};
+
+// Find the preferred loading address of the binary.
+template<typename ElfClass>
+typename ElfClass::Addr GetLoadingAddress(
+ const typename ElfClass::Phdr* program_headers,
+ int nheader) {
+ typedef typename ElfClass::Phdr Phdr;
+
+ // For non-PIC executables (e_type == ET_EXEC), the load address is
+ // the start address of the first PT_LOAD segment. (ELF requires
+ // the segments to be sorted by load address.) For PIC executables
+ // and dynamic libraries (e_type == ET_DYN), this address will
+ // normally be zero.
+ for (int i = 0; i < nheader; ++i) {
+ const Phdr& header = program_headers[i];
+ if (header.p_type == PT_LOAD)
+ return header.p_vaddr;
+ }
+ return 0;
+}
+
+// Find the set of address ranges for all PT_LOAD segments.
+template <typename ElfClass>
+vector<Module::Range> GetPtLoadSegmentRanges(
+ const typename ElfClass::Phdr* program_headers,
+ int nheader) {
+ typedef typename ElfClass::Phdr Phdr;
+ vector<Module::Range> ranges;
+
+ for (int i = 0; i < nheader; ++i) {
+ const Phdr& header = program_headers[i];
+ if (header.p_type == PT_LOAD) {
+ ranges.push_back(Module::Range(header.p_vaddr, header.p_memsz));
+ }
+ }
+ return ranges;
+}
+
+#ifndef NO_STABS_SUPPORT
+template<typename ElfClass>
+bool LoadStabs(const typename ElfClass::Ehdr* elf_header,
+ const typename ElfClass::Shdr* stab_section,
+ const typename ElfClass::Shdr* stabstr_section,
+ const bool big_endian,
+ Module* module) {
+ // A callback object to handle data from the STABS reader.
+ StabsToModule handler(module);
+ // Find the addresses of the STABS data, and create a STABS reader object.
+ // On Linux, STABS entries always have 32-bit values, regardless of the
+ // address size of the architecture whose code they're describing, and
+ // the strings are always "unitized".
+ const uint8_t* stabs =
+ GetOffset<ElfClass, uint8_t>(elf_header, stab_section->sh_offset);
+ const uint8_t* stabstr =
+ GetOffset<ElfClass, uint8_t>(elf_header, stabstr_section->sh_offset);
+ google_breakpad::StabsReader reader(stabs, stab_section->sh_size,
+ stabstr, stabstr_section->sh_size,
+ big_endian, 4, true, &handler);
+ // Read the STABS data, and do post-processing.
+ if (!reader.Process())
+ return false;
+ handler.Finalize();
+ return true;
+}
+#endif // NO_STABS_SUPPORT
+
+// A range handler that accepts rangelist data parsed by
+// google_breakpad::RangeListReader and populates a range vector (typically
+// owned by a function) with the results.
+class DumperRangesHandler : public DwarfCUToModule::RangesHandler {
+ public:
+ DumperRangesHandler(google_breakpad::ByteReader* reader) :
+ reader_(reader) { }
+
+ bool ReadRanges(
+ enum google_breakpad::DwarfForm form, uint64_t data,
+ google_breakpad::RangeListReader::CURangesInfo* cu_info,
+ vector<Module::Range>* ranges) {
+ DwarfRangeListHandler handler(ranges);
+ google_breakpad::RangeListReader range_list_reader(reader_, cu_info,
+ &handler);
+ return range_list_reader.ReadRanges(form, data);
+ }
+
+ private:
+ google_breakpad::ByteReader* reader_;
+};
+
+// A line-to-module loader that accepts line number info parsed by
+// google_breakpad::LineInfo and populates a Module and a line vector
+// with the results.
+class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler {
+ public:
+ // Create a line-to-module converter using BYTE_READER.
+ explicit DumperLineToModule(google_breakpad::ByteReader* byte_reader)
+ : byte_reader_(byte_reader) { }
+ void StartCompilationUnit(const string& compilation_dir) {
+ compilation_dir_ = compilation_dir;
+ }
+ void ReadProgram(const uint8_t* program,
+ uint64_t length,
+ const uint8_t* string_section,
+ uint64_t string_section_length,
+ const uint8_t* line_string_section,
+ uint64_t line_string_section_length,
+ Module* module,
+ std::vector<Module::Line>* lines,
+ std::map<uint32_t, Module::File*>* files) {
+ DwarfLineToModule handler(module, compilation_dir_, lines, files);
+ google_breakpad::LineInfo parser(program, length, byte_reader_,
+ string_section, string_section_length,
+ line_string_section,
+ line_string_section_length,
+ &handler);
+ parser.Start();
+ }
+ private:
+ string compilation_dir_;
+ google_breakpad::ByteReader* byte_reader_;
+};
+
+template<typename ElfClass>
+bool LoadDwarf(const string& dwarf_filename,
+ const typename ElfClass::Ehdr* elf_header,
+ const bool big_endian,
+ bool handle_inter_cu_refs,
+ bool handle_inline,
+ Module* module) {
+ typedef typename ElfClass::Shdr Shdr;
+
+ const google_breakpad::Endianness endianness = big_endian ?
+ google_breakpad::ENDIANNESS_BIG : google_breakpad::ENDIANNESS_LITTLE;
+ google_breakpad::ByteReader byte_reader(endianness);
+
+ // Construct a context for this file.
+ DwarfCUToModule::FileContext file_context(dwarf_filename,
+ module,
+ handle_inter_cu_refs);
+
+ // Build a map of the ELF file's sections.
+ const Shdr* sections =
+ GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
+ int num_sections = elf_header->e_shnum;
+ const Shdr* section_names = sections + elf_header->e_shstrndx;
+ for (int i = 0; i < num_sections; i++) {
+ const Shdr* section = &sections[i];
+ string name = GetOffset<ElfClass, char>(elf_header,
+ section_names->sh_offset) +
+ section->sh_name;
+ const uint8_t* contents = GetOffset<ElfClass, uint8_t>(elf_header,
+ section->sh_offset);
+ file_context.AddSectionToSectionMap(name, contents, section->sh_size);
+ }
+
+ // .debug_ranges and .debug_rnglists reader
+ DumperRangesHandler ranges_handler(&byte_reader);
+
+ // Parse all the compilation units in the .debug_info section.
+ DumperLineToModule line_to_module(&byte_reader);
+ google_breakpad::SectionMap::const_iterator debug_info_entry =
+ file_context.section_map().find(".debug_info");
+ assert(debug_info_entry != file_context.section_map().end());
+ const std::pair<const uint8_t*, uint64_t>& debug_info_section =
+ debug_info_entry->second;
+ // This should never have been called if the file doesn't have a
+ // .debug_info section.
+ assert(debug_info_section.first);
+ uint64_t debug_info_length = debug_info_section.second;
+ for (uint64_t offset = 0; offset < debug_info_length;) {
+ // Make a handler for the root DIE that populates MODULE with the
+ // data that was found.
+ DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset);
+ DwarfCUToModule root_handler(&file_context, &line_to_module,
+ &ranges_handler, &reporter, handle_inline);
+ // Make a Dwarf2Handler that drives the DIEHandler.
+ google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
+ // Make a DWARF parser for the compilation unit at OFFSET.
+ google_breakpad::CompilationUnit reader(dwarf_filename,
+ file_context.section_map(),
+ offset,
+ &byte_reader,
+ &die_dispatcher);
+ // Process the entire compilation unit; get the offset of the next.
+ offset += reader.Start();
+ }
+ return true;
+}
+
+// Fill REGISTER_NAMES with the register names appropriate to the
+// machine architecture given in HEADER, indexed by the register
+// numbers used in DWARF call frame information. Return true on
+// success, or false if HEADER's machine architecture is not
+// supported.
+template<typename ElfClass>
+bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
+ std::vector<string>* register_names) {
+ switch (elf_header->e_machine) {
+ case EM_386:
+ *register_names = DwarfCFIToModule::RegisterNames::I386();
+ return true;
+ case EM_ARM:
+ *register_names = DwarfCFIToModule::RegisterNames::ARM();
+ return true;
+ case EM_AARCH64:
+ *register_names = DwarfCFIToModule::RegisterNames::ARM64();
+ return true;
+ case EM_MIPS:
+ *register_names = DwarfCFIToModule::RegisterNames::MIPS();
+ return true;
+ case EM_X86_64:
+ *register_names = DwarfCFIToModule::RegisterNames::X86_64();
+ return true;
+ default:
+ return false;
+ }
+}
+
+template<typename ElfClass>
+bool LoadDwarfCFI(const string& dwarf_filename,
+ const typename ElfClass::Ehdr* elf_header,
+ const char* section_name,
+ const typename ElfClass::Shdr* section,
+ const bool eh_frame,
+ const typename ElfClass::Shdr* got_section,
+ const typename ElfClass::Shdr* text_section,
+ const bool big_endian,
+ Module* module) {
+ // Find the appropriate set of register names for this file's
+ // architecture.
+ std::vector<string> register_names;
+ if (!DwarfCFIRegisterNames<ElfClass>(elf_header, &register_names)) {
+ fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';"
+ " cannot convert DWARF call frame information\n",
+ dwarf_filename.c_str(), elf_header->e_machine);
+ return false;
+ }
+
+ const google_breakpad::Endianness endianness = big_endian ?
+ google_breakpad::ENDIANNESS_BIG : google_breakpad::ENDIANNESS_LITTLE;
+
+ // Find the call frame information and its size.
+ const uint8_t* cfi =
+ GetOffset<ElfClass, uint8_t>(elf_header, section->sh_offset);
+ size_t cfi_size = section->sh_size;
+
+ // Plug together the parser, handler, and their entourages.
+ DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name);
+ DwarfCFIToModule handler(module, register_names, &module_reporter);
+ google_breakpad::ByteReader byte_reader(endianness);
+
+ byte_reader.SetAddressSize(ElfClass::kAddrSize);
+
+ // Provide the base addresses for .eh_frame encoded pointers, if
+ // possible.
+ byte_reader.SetCFIDataBase(section->sh_addr, cfi);
+ if (got_section)
+ byte_reader.SetDataBase(got_section->sh_addr);
+ if (text_section)
+ byte_reader.SetTextBase(text_section->sh_addr);
+
+ google_breakpad::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename,
+ section_name);
+ google_breakpad::CallFrameInfo parser(cfi, cfi_size,
+ &byte_reader, &handler, &dwarf_reporter,
+ eh_frame);
+ parser.Start();
+ return true;
+}
+
+bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper,
+ void** elf_header) {
+ int obj_fd = open(obj_file.c_str(), O_RDONLY);
+ if (obj_fd < 0) {
+ fprintf(stderr, "Failed to open ELF file '%s': %s\n",
+ obj_file.c_str(), strerror(errno));
+ return false;
+ }
+ FDWrapper obj_fd_wrapper(obj_fd);
+ struct stat st;
+ if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) {
+ fprintf(stderr, "Unable to fstat ELF file '%s': %s\n",
+ obj_file.c_str(), strerror(errno));
+ return false;
+ }
+ void* obj_base = mmap(NULL, st.st_size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0);
+ if (obj_base == MAP_FAILED) {
+ fprintf(stderr, "Failed to mmap ELF file '%s': %s\n",
+ obj_file.c_str(), strerror(errno));
+ return false;
+ }
+ map_wrapper->set(obj_base, st.st_size);
+ *elf_header = obj_base;
+ if (!IsValidElf(*elf_header)) {
+ fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
+ return false;
+ }
+ return true;
+}
+
+// Get the endianness of ELF_HEADER. If it's invalid, return false.
+template<typename ElfClass>
+bool ElfEndianness(const typename ElfClass::Ehdr* elf_header,
+ bool* big_endian) {
+ if (elf_header->e_ident[EI_DATA] == ELFDATA2LSB) {
+ *big_endian = false;
+ return true;
+ }
+ if (elf_header->e_ident[EI_DATA] == ELFDATA2MSB) {
+ *big_endian = true;
+ return true;
+ }
+
+ fprintf(stderr, "bad data encoding in ELF header: %d\n",
+ elf_header->e_ident[EI_DATA]);
+ return false;
+}
+
+// Given |left_abspath|, find the absolute path for |right_path| and see if the
+// two absolute paths are the same.
+bool IsSameFile(const char* left_abspath, const string& right_path) {
+ char right_abspath[PATH_MAX];
+ if (!realpath(right_path.c_str(), right_abspath))
+ return false;
+ return strcmp(left_abspath, right_abspath) == 0;
+}
+
+// Read the .gnu_debuglink and get the debug file name. If anything goes
+// wrong, return an empty string.
+string ReadDebugLink(const uint8_t* debuglink,
+ const size_t debuglink_size,
+ const bool big_endian,
+ const string& obj_file,
+ const std::vector<string>& debug_dirs) {
+ // Include '\0' + CRC32 (4 bytes).
+ size_t debuglink_len = strlen(reinterpret_cast<const char*>(debuglink)) + 5;
+ debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round up to 4 bytes.
+
+ // Sanity check.
+ if (debuglink_len != debuglink_size) {
+ fprintf(stderr, "Mismatched .gnu_debuglink string / section size: "
+ "%zx %zx\n", debuglink_len, debuglink_size);
+ return string();
+ }
+
+ char obj_file_abspath[PATH_MAX];
+ if (!realpath(obj_file.c_str(), obj_file_abspath)) {
+ fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str());
+ return string();
+ }
+
+ std::vector<string> searched_paths;
+ string debuglink_path;
+ std::vector<string>::const_iterator it;
+ for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) {
+ const string& debug_dir = *it;
+ debuglink_path = debug_dir + "/" +
+ reinterpret_cast<const char*>(debuglink);
+
+ // There is the annoying case of /path/to/foo.so having foo.so as the
+ // debug link file name. Thus this may end up opening /path/to/foo.so again,
+ // and there is a small chance of the two files having the same CRC.
+ if (IsSameFile(obj_file_abspath, debuglink_path))
+ continue;
+
+ searched_paths.push_back(debug_dir);
+ int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
+ if (debuglink_fd < 0)
+ continue;
+
+ FDWrapper debuglink_fd_wrapper(debuglink_fd);
+
+ // The CRC is the last 4 bytes in |debuglink|.
+ const google_breakpad::Endianness endianness = big_endian ?
+ google_breakpad::ENDIANNESS_BIG : google_breakpad::ENDIANNESS_LITTLE;
+ google_breakpad::ByteReader byte_reader(endianness);
+ uint32_t expected_crc =
+ byte_reader.ReadFourBytes(&debuglink[debuglink_size - 4]);
+
+ uint32_t actual_crc = 0;
+ while (true) {
+ const size_t kReadSize = 4096;
+ char buf[kReadSize];
+ ssize_t bytes_read = HANDLE_EINTR(read(debuglink_fd, &buf, kReadSize));
+ if (bytes_read < 0) {
+ fprintf(stderr, "Error reading debug ELF file %s.\n",
+ debuglink_path.c_str());
+ return string();
+ }
+ if (bytes_read == 0)
+ break;
+ actual_crc = google_breakpad::UpdateCrc32(actual_crc, buf, bytes_read);
+ }
+ if (actual_crc != expected_crc) {
+ fprintf(stderr, "Error reading debug ELF file - CRC32 mismatch: %s\n",
+ debuglink_path.c_str());
+ continue;
+ }
+
+ // Found debug file.
+ return debuglink_path;
+ }
+
+ // Not found case.
+ fprintf(stderr, "Failed to find debug ELF file for '%s' after trying:\n",
+ obj_file.c_str());
+ for (it = searched_paths.begin(); it < searched_paths.end(); ++it) {
+ const string& debug_dir = *it;
+ fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink);
+ }
+ return string();
+}
+
+//
+// LoadSymbolsInfo
+//
+// Holds the state between the two calls to LoadSymbols() in case it's necessary
+// to follow the .gnu_debuglink section and load debug information from a
+// different file.
+//
+template<typename ElfClass>
+class LoadSymbolsInfo {
+ public:
+ typedef typename ElfClass::Addr Addr;
+
+ explicit LoadSymbolsInfo(const std::vector<string>& dbg_dirs) :
+ debug_dirs_(dbg_dirs),
+ has_loading_addr_(false) {}
+
+ // Keeps track of which sections have been loaded so sections don't
+ // accidentally get loaded twice from two different files.
+ void LoadedSection(const string& section) {
+ if (loaded_sections_.count(section) == 0) {
+ loaded_sections_.insert(section);
+ } else {
+ fprintf(stderr, "Section %s has already been loaded.\n",
+ section.c_str());
+ }
+ }
+
+ // The ELF file and linked debug file are expected to have the same preferred
+ // loading address.
+ void set_loading_addr(Addr addr, const string& filename) {
+ if (!has_loading_addr_) {
+ loading_addr_ = addr;
+ loaded_file_ = filename;
+ return;
+ }
+
+ if (addr != loading_addr_) {
+ fprintf(stderr,
+ "ELF file '%s' and debug ELF file '%s' "
+ "have different load addresses.\n",
+ loaded_file_.c_str(), filename.c_str());
+ assert(false);
+ }
+ }
+
+ // Setters and getters
+ const std::vector<string>& debug_dirs() const {
+ return debug_dirs_;
+ }
+
+ string debuglink_file() const {
+ return debuglink_file_;
+ }
+ void set_debuglink_file(string file) {
+ debuglink_file_ = file;
+ }
+
+ private:
+ const std::vector<string>& debug_dirs_; // Directories in which to
+ // search for the debug ELF file.
+
+ string debuglink_file_; // Full path to the debug ELF file.
+
+ bool has_loading_addr_; // Indicate if LOADING_ADDR_ is valid.
+
+ Addr loading_addr_; // Saves the preferred loading address from the
+ // first call to LoadSymbols().
+
+ string loaded_file_; // Name of the file loaded from the first call to
+ // LoadSymbols().
+
+ std::set<string> loaded_sections_; // Tracks the Loaded ELF sections
+ // between calls to LoadSymbols().
+};
+
+template<typename ElfClass>
+bool LoadSymbols(const string& obj_file,
+ const bool big_endian,
+ const typename ElfClass::Ehdr* elf_header,
+ const bool read_gnu_debug_link,
+ LoadSymbolsInfo<ElfClass>* info,
+ const DumpOptions& options,
+ Module* module) {
+ typedef typename ElfClass::Addr Addr;
+ typedef typename ElfClass::Phdr Phdr;
+ typedef typename ElfClass::Shdr Shdr;
+
+ Addr loading_addr = GetLoadingAddress<ElfClass>(
+ GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff),
+ elf_header->e_phnum);
+ module->SetLoadAddress(loading_addr);
+ info->set_loading_addr(loading_addr, obj_file);
+
+ // Allow filtering of extraneous debug information in partitioned libraries.
+ // Such libraries contain debug information for all libraries extracted from
+ // the same combined library, implying extensive duplication.
+ vector<Module::Range> address_ranges = GetPtLoadSegmentRanges<ElfClass>(
+ GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff),
+ elf_header->e_phnum);
+ module->SetAddressRanges(address_ranges);
+
+ const Shdr* sections =
+ GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
+ const Shdr* section_names = sections + elf_header->e_shstrndx;
+ const char* names =
+ GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
+ const char* names_end = names + section_names->sh_size;
+ bool found_debug_info_section = false;
+ bool found_usable_info = false;
+
+ if ((options.symbol_data & SYMBOLS_AND_FILES) ||
+ (options.symbol_data & INLINES)) {
+#ifndef NO_STABS_SUPPORT
+ // Look for STABS debugging information, and load it if present.
+ const Shdr* stab_section =
+ FindElfSectionByName<ElfClass>(".stab", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ if (stab_section) {
+ const Shdr* stabstr_section = stab_section->sh_link + sections;
+ if (stabstr_section) {
+ found_debug_info_section = true;
+ found_usable_info = true;
+ info->LoadedSection(".stab");
+ if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section,
+ big_endian, module)) {
+ fprintf(stderr, "%s: \".stab\" section found, but failed to load"
+ " STABS debugging information\n", obj_file.c_str());
+ }
+ }
+ }
+#endif // NO_STABS_SUPPORT
+
+ // See if there are export symbols available.
+ const Shdr* symtab_section =
+ FindElfSectionByName<ElfClass>(".symtab", SHT_SYMTAB,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ const Shdr* strtab_section =
+ FindElfSectionByName<ElfClass>(".strtab", SHT_STRTAB,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ if (symtab_section && strtab_section) {
+ info->LoadedSection(".symtab");
+
+ const uint8_t* symtab =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ symtab_section->sh_offset);
+ const uint8_t* strtab =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ strtab_section->sh_offset);
+ bool result =
+ ELFSymbolsToModule(symtab,
+ symtab_section->sh_size,
+ strtab,
+ strtab_section->sh_size,
+ big_endian,
+ ElfClass::kAddrSize,
+ module);
+ found_usable_info = found_usable_info || result;
+ } else {
+ // Look in dynsym only if full symbol table was not available.
+ const Shdr* dynsym_section =
+ FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ const Shdr* dynstr_section =
+ FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ if (dynsym_section && dynstr_section) {
+ info->LoadedSection(".dynsym");
+
+ const uint8_t* dynsyms =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ dynsym_section->sh_offset);
+ const uint8_t* dynstrs =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ dynstr_section->sh_offset);
+ bool result =
+ ELFSymbolsToModule(dynsyms,
+ dynsym_section->sh_size,
+ dynstrs,
+ dynstr_section->sh_size,
+ big_endian,
+ ElfClass::kAddrSize,
+ module);
+ found_usable_info = found_usable_info || result;
+ }
+ }
+
+ // Only Load .debug_info after loading symbol table to avoid duplicate
+ // PUBLIC records.
+ // Look for DWARF debugging information, and load it if present.
+ const Shdr* dwarf_section =
+ FindElfSectionByName<ElfClass>(".debug_info", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+
+ // .debug_info section type is SHT_PROGBITS for mips on pnacl toolchains,
+ // but MIPS_DWARF for regular gnu toolchains, so both need to be checked
+ if (elf_header->e_machine == EM_MIPS && !dwarf_section) {
+ dwarf_section =
+ FindElfSectionByName<ElfClass>(".debug_info", SHT_MIPS_DWARF,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ }
+
+ if (dwarf_section) {
+ found_debug_info_section = true;
+ found_usable_info = true;
+ info->LoadedSection(".debug_info");
+ if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian,
+ options.handle_inter_cu_refs,
+ options.symbol_data & INLINES, module)) {
+ fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
+ "DWARF debugging information\n", obj_file.c_str());
+ }
+ }
+ }
+
+ if (options.symbol_data & CFI) {
+ // Dwarf Call Frame Information (CFI) is actually independent from
+ // the other DWARF debugging information, and can be used alone.
+ const Shdr* dwarf_cfi_section =
+ FindElfSectionByName<ElfClass>(".debug_frame", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+
+ // .debug_frame section type is SHT_PROGBITS for mips on pnacl toolchains,
+ // but MIPS_DWARF for regular gnu toolchains, so both need to be checked
+ if (elf_header->e_machine == EM_MIPS && !dwarf_cfi_section) {
+ dwarf_cfi_section =
+ FindElfSectionByName<ElfClass>(".debug_frame", SHT_MIPS_DWARF,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ }
+
+ if (dwarf_cfi_section) {
+ // Ignore the return value of this function; even without call frame
+ // information, the other debugging information could be perfectly
+ // useful.
+ info->LoadedSection(".debug_frame");
+ bool result =
+ LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".debug_frame",
+ dwarf_cfi_section, false, 0, 0, big_endian,
+ module);
+ found_usable_info = found_usable_info || result;
+ }
+
+ // Linux C++ exception handling information can also provide
+ // unwinding data.
+ const Shdr* eh_frame_section =
+ FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ if (eh_frame_section) {
+ // Pointers in .eh_frame data may be relative to the base addresses of
+ // certain sections. Provide those sections if present.
+ const Shdr* got_section =
+ FindElfSectionByName<ElfClass>(".got", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ const Shdr* text_section =
+ FindElfSectionByName<ElfClass>(".text", SHT_PROGBITS,
+ sections, names, names_end,
+ elf_header->e_shnum);
+ info->LoadedSection(".eh_frame");
+ // As above, ignore the return value of this function.
+ bool result =
+ LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame",
+ eh_frame_section, true,
+ got_section, text_section, big_endian, module);
+ found_usable_info = found_usable_info || result;
+ }
+ }
+
+ if (!found_debug_info_section) {
+ fprintf(stderr, "%s: file contains no debugging information"
+ " (no \".stab\" or \".debug_info\" sections)\n",
+ obj_file.c_str());
+
+ // Failed, but maybe there's a .gnu_debuglink section?
+ if (read_gnu_debug_link) {
+ const Shdr* gnu_debuglink_section
+ = FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS,
+ sections, names,
+ names_end, elf_header->e_shnum);
+ if (gnu_debuglink_section) {
+ if (!info->debug_dirs().empty()) {
+ const uint8_t* debuglink_contents =
+ GetOffset<ElfClass, uint8_t>(elf_header,
+ gnu_debuglink_section->sh_offset);
+ string debuglink_file =
+ ReadDebugLink(debuglink_contents,
+ gnu_debuglink_section->sh_size,
+ big_endian,
+ obj_file,
+ info->debug_dirs());
+ info->set_debuglink_file(debuglink_file);
+ } else {
+ fprintf(stderr, ".gnu_debuglink section found in '%s', "
+ "but no debug path specified.\n", obj_file.c_str());
+ }
+ } else {
+ fprintf(stderr, "%s does not contain a .gnu_debuglink section.\n",
+ obj_file.c_str());
+ }
+ } else {
+ // Return true if some usable information was found, since the caller
+ // doesn't want to use .gnu_debuglink.
+ return found_usable_info;
+ }
+
+ // No debug info was found, let the user try again with .gnu_debuglink
+ // if present.
+ return false;
+ }
+
+ return true;
+}
+
+// Return the breakpad symbol file identifier for the architecture of
+// ELF_HEADER.
+template<typename ElfClass>
+const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) {
+ typedef typename ElfClass::Half Half;
+ Half arch = elf_header->e_machine;
+ switch (arch) {
+ case EM_386: return "x86";
+ case EM_ARM: return "arm";
+ case EM_AARCH64: return "arm64";
+ case EM_MIPS: return "mips";
+ case EM_PPC64: return "ppc64";
+ case EM_PPC: return "ppc";
+ case EM_S390: return "s390";
+ case EM_SPARC: return "sparc";
+ case EM_SPARCV9: return "sparcv9";
+ case EM_X86_64: return "x86_64";
+ default: return NULL;
+ }
+}
+
+template<typename ElfClass>
+bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header,
+ const string& debuglink_file,
+ const string& obj_filename,
+ const char* obj_file_architecture,
+ const bool obj_file_is_big_endian) {
+ const char* debug_architecture =
+ ElfArchitecture<ElfClass>(debug_elf_header);
+ if (!debug_architecture) {
+ fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
+ debuglink_file.c_str(), debug_elf_header->e_machine);
+ return false;
+ }
+ if (strcmp(obj_file_architecture, debug_architecture)) {
+ fprintf(stderr, "%s with ELF machine architecture %s does not match "
+ "%s with ELF architecture %s\n",
+ debuglink_file.c_str(), debug_architecture,
+ obj_filename.c_str(), obj_file_architecture);
+ return false;
+ }
+ bool debug_big_endian;
+ if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian))
+ return false;
+ if (debug_big_endian != obj_file_is_big_endian) {
+ fprintf(stderr, "%s and %s does not match in endianness\n",
+ obj_filename.c_str(), debuglink_file.c_str());
+ return false;
+ }
+ return true;
+}
+
+template<typename ElfClass>
+bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header,
+ const string& obj_filename,
+ const string& obj_os,
+ scoped_ptr<Module>& module) {
+ PageAllocator allocator;
+ wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
+ if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) {
+ fprintf(stderr, "%s: unable to generate file identifier\n",
+ obj_filename.c_str());
+ return false;
+ }
+
+ const char* architecture = ElfArchitecture<ElfClass>(elf_header);
+ if (!architecture) {
+ fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
+ obj_filename.c_str(), elf_header->e_machine);
+ return false;
+ }
+
+ char name_buf[NAME_MAX] = {};
+ std::string name = google_breakpad::ElfFileSoNameFromMappedFile(
+ elf_header, name_buf, sizeof(name_buf))
+ ? name_buf
+ : google_breakpad::BaseName(obj_filename);
+
+ // Add an extra "0" at the end. PDB files on Windows have an 'age'
+ // number appended to the end of the file identifier; this isn't
+ // really used or necessary on other platforms, but be consistent.
+ string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0";
+ // This is just the raw Build ID in hex.
+ string code_id = FileID::ConvertIdentifierToString(identifier);
+
+ module.reset(new Module(name, obj_os, architecture, id, code_id));
+
+ return true;
+}
+
+template<typename ElfClass>
+bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
+ const string& obj_filename,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ Module** out_module) {
+ typedef typename ElfClass::Ehdr Ehdr;
+
+ *out_module = NULL;
+
+ scoped_ptr<Module> module;
+ if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, obj_os,
+ module)) {
+ return false;
+ }
+
+ // Figure out what endianness this file is.
+ bool big_endian;
+ if (!ElfEndianness<ElfClass>(elf_header, &big_endian))
+ return false;
+
+ LoadSymbolsInfo<ElfClass> info(debug_dirs);
+ if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
+ !debug_dirs.empty(), &info,
+ options, module.get())) {
+ const string debuglink_file = info.debuglink_file();
+ if (debuglink_file.empty())
+ return false;
+
+ // Load debuglink ELF file.
+ fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str());
+ MmapWrapper debug_map_wrapper;
+ Ehdr* debug_elf_header = NULL;
+ if (!LoadELF(debuglink_file, &debug_map_wrapper,
+ reinterpret_cast<void**>(&debug_elf_header)) ||
+ !SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file,
+ obj_filename,
+ module->architecture().c_str(),
+ big_endian)) {
+ return false;
+ }
+
+ if (!LoadSymbols<ElfClass>(debuglink_file, big_endian,
+ debug_elf_header, false, &info,
+ options, module.get())) {
+ return false;
+ }
+ }
+
+ *out_module = module.release();
+ return true;
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+// Not explicitly exported, but not static so it can be used in unit tests.
+bool ReadSymbolDataInternal(const uint8_t* obj_file,
+ const string& obj_filename,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ Module** module) {
+ if (!IsValidElf(obj_file)) {
+ fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str());
+ return false;
+ }
+
+ int elfclass = ElfClass(obj_file);
+ if (elfclass == ELFCLASS32) {
+ return ReadSymbolDataElfClass<ElfClass32>(
+ reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, obj_os,
+ debug_dirs, options, module);
+ }
+ if (elfclass == ELFCLASS64) {
+ return ReadSymbolDataElfClass<ElfClass64>(
+ reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, obj_os,
+ debug_dirs, options, module);
+ }
+
+ return false;
+}
+
+bool WriteSymbolFile(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ std::ostream& sym_stream) {
+ Module* module;
+ if (!ReadSymbolData(load_path, obj_file, obj_os, debug_dirs, options,
+ &module))
+ return false;
+
+ bool result = module->Write(sym_stream, options.symbol_data);
+ delete module;
+ return result;
+}
+
+// Read the selected object file's debugging information, and write out the
+// header only to |stream|. Return true on success; if an error occurs, report
+// it and return false.
+bool WriteSymbolFileHeader(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ std::ostream& sym_stream) {
+ MmapWrapper map_wrapper;
+ void* elf_header = NULL;
+ if (!LoadELF(load_path, &map_wrapper, &elf_header)) {
+ fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str());
+ return false;
+ }
+
+ if (!IsValidElf(elf_header)) {
+ fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
+ return false;
+ }
+
+ int elfclass = ElfClass(elf_header);
+ scoped_ptr<Module> module;
+ if (elfclass == ELFCLASS32) {
+ if (!InitModuleForElfClass<ElfClass32>(
+ reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, obj_os,
+ module)) {
+ fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
+ return false;
+ }
+ } else if (elfclass == ELFCLASS64) {
+ if (!InitModuleForElfClass<ElfClass64>(
+ reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, obj_os,
+ module)) {
+ fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
+ return false;
+ }
+ } else {
+ fprintf(stderr, "Unsupported module file: %s\n", obj_file.c_str());
+ return false;
+ }
+
+ return module->Write(sym_stream, ALL_SYMBOL_DATA);
+}
+
+bool ReadSymbolData(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ Module** module) {
+ MmapWrapper map_wrapper;
+ void* elf_header = NULL;
+ if (!LoadELF(load_path, &map_wrapper, &elf_header))
+ return false;
+
+ return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
+ obj_file, obj_os, debug_dirs, options, module);
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/dump_symbols.h b/contrib/libs/breakpad/src/common/linux/dump_symbols.h
new file mode 100644
index 0000000000..b033ce00ea
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/dump_symbols.h
@@ -0,0 +1,93 @@
+// -*- mode: c++ -*-
+
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// dump_symbols.h: Read debugging information from an ELF file, and write
+// it out as a Breakpad symbol file.
+
+#ifndef COMMON_LINUX_DUMP_SYMBOLS_H__
+#define COMMON_LINUX_DUMP_SYMBOLS_H__
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "common/symbol_data.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+class Module;
+
+struct DumpOptions {
+ DumpOptions(SymbolData symbol_data, bool handle_inter_cu_refs)
+ : symbol_data(symbol_data),
+ handle_inter_cu_refs(handle_inter_cu_refs) {
+ }
+
+ SymbolData symbol_data;
+ bool handle_inter_cu_refs;
+};
+
+// Find all the debugging information in OBJ_FILE, an ELF executable
+// or shared library, and write it to SYM_STREAM in the Breakpad symbol
+// file format.
+// If OBJ_FILE has been stripped but contains a .gnu_debuglink section,
+// then look for the debug file in DEBUG_DIRS.
+// SYMBOL_DATA allows limiting the type of symbol data written.
+bool WriteSymbolFile(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ std::ostream& sym_stream);
+
+// Read the selected object file's debugging information, and write out the
+// header only to |stream|. Return true on success; if an error occurs, report
+// it and return false. |obj_file| becomes the MODULE file name and |obj_os|
+// becomes the MODULE operating system.
+bool WriteSymbolFileHeader(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ std::ostream& sym_stream);
+
+// As above, but simply return the debugging information in MODULE
+// instead of writing it to a stream. The caller owns the resulting
+// Module object and must delete it when finished.
+bool ReadSymbolData(const string& load_path,
+ const string& obj_file,
+ const string& obj_os,
+ const std::vector<string>& debug_dirs,
+ const DumpOptions& options,
+ Module** module);
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
diff --git a/contrib/libs/breakpad/src/common/linux/eintr_wrapper.h b/contrib/libs/breakpad/src/common/linux/eintr_wrapper.h
new file mode 100644
index 0000000000..3f1d184817
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/eintr_wrapper.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2010 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_EINTR_WRAPPER_H_
+#define COMMON_LINUX_EINTR_WRAPPER_H_
+
+#include <errno.h>
+
+// This provides a wrapper around system calls which may be interrupted by a
+// signal and return EINTR. See man 7 signal.
+//
+
+#define HANDLE_EINTR(x) ({ \
+ __typeof__(x) eintr_wrapper_result; \
+ do { \
+ eintr_wrapper_result = (x); \
+ } while (eintr_wrapper_result == -1 && errno == EINTR); \
+ eintr_wrapper_result; \
+})
+
+#define IGNORE_EINTR(x) ({ \
+ __typeof__(x) eintr_wrapper_result; \
+ do { \
+ eintr_wrapper_result = (x); \
+ if (eintr_wrapper_result == -1 && errno == EINTR) { \
+ eintr_wrapper_result = 0; \
+ } \
+ } while (0); \
+ eintr_wrapper_result; \
+})
+
+#endif // COMMON_LINUX_EINTR_WRAPPER_H_
diff --git a/contrib/libs/breakpad/src/common/linux/elf_core_dump.cc b/contrib/libs/breakpad/src/common/linux/elf_core_dump.cc
new file mode 100644
index 0000000000..f3206092b3
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elf_core_dump.cc
@@ -0,0 +1,203 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump.
+// See elf_core_dump.h for details.
+
+#include "common/linux/elf_core_dump.h"
+
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+
+namespace google_breakpad {
+
+// Implementation of ElfCoreDump::Note.
+
+ElfCoreDump::Note::Note() {}
+
+ElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {}
+
+bool ElfCoreDump::Note::IsValid() const {
+ return GetHeader() != NULL;
+}
+
+const ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const {
+ return content_.GetData<Nhdr>(0);
+}
+
+ElfCoreDump::Word ElfCoreDump::Note::GetType() const {
+ const Nhdr* header = GetHeader();
+ // 0 is not being used as a NOTE type.
+ return header ? header->n_type : 0;
+}
+
+MemoryRange ElfCoreDump::Note::GetName() const {
+ const Nhdr* header = GetHeader();
+ if (header) {
+ return content_.Subrange(sizeof(Nhdr), header->n_namesz);
+ }
+ return MemoryRange();
+}
+
+MemoryRange ElfCoreDump::Note::GetDescription() const {
+ const Nhdr* header = GetHeader();
+ if (header) {
+ return content_.Subrange(AlignedSize(sizeof(Nhdr) + header->n_namesz),
+ header->n_descsz);
+ }
+ return MemoryRange();
+}
+
+ElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const {
+ MemoryRange next_content;
+ const Nhdr* header = GetHeader();
+ if (header) {
+ size_t next_offset = AlignedSize(sizeof(Nhdr) + header->n_namesz);
+ next_offset = AlignedSize(next_offset + header->n_descsz);
+ next_content =
+ content_.Subrange(next_offset, content_.length() - next_offset);
+ }
+ return Note(next_content);
+}
+
+// static
+size_t ElfCoreDump::Note::AlignedSize(size_t size) {
+ size_t mask = sizeof(Word) - 1;
+ return (size + mask) & ~mask;
+}
+
+
+// Implementation of ElfCoreDump.
+
+ElfCoreDump::ElfCoreDump() : proc_mem_fd_(-1) {}
+
+ElfCoreDump::ElfCoreDump(const MemoryRange& content)
+ : content_(content), proc_mem_fd_(-1) {}
+
+ElfCoreDump::~ElfCoreDump() {
+ if (proc_mem_fd_ != -1) {
+ close(proc_mem_fd_);
+ proc_mem_fd_ = -1;
+ }
+}
+
+void ElfCoreDump::SetContent(const MemoryRange& content) {
+ content_ = content;
+}
+
+void ElfCoreDump::SetProcMem(int fd) {
+ if (proc_mem_fd_ != -1) {
+ close(proc_mem_fd_);
+ }
+ proc_mem_fd_ = fd;
+}
+
+bool ElfCoreDump::IsValid() const {
+ const Ehdr* header = GetHeader();
+ return (header &&
+ header->e_ident[0] == ELFMAG0 &&
+ header->e_ident[1] == ELFMAG1 &&
+ header->e_ident[2] == ELFMAG2 &&
+ header->e_ident[3] == ELFMAG3 &&
+ header->e_ident[4] == kClass &&
+ header->e_version == EV_CURRENT &&
+ header->e_type == ET_CORE);
+}
+
+const ElfCoreDump::Ehdr* ElfCoreDump::GetHeader() const {
+ return content_.GetData<Ehdr>(0);
+}
+
+const ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const {
+ const Ehdr* header = GetHeader();
+ if (header) {
+ return reinterpret_cast<const Phdr*>(content_.GetArrayElement(
+ header->e_phoff, header->e_phentsize, index));
+ }
+ return NULL;
+}
+
+const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType(
+ Word type) const {
+ for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) {
+ const Phdr* program = GetProgramHeader(i);
+ if (program->p_type == type) {
+ return program;
+ }
+ }
+ return NULL;
+}
+
+unsigned ElfCoreDump::GetProgramHeaderCount() const {
+ const Ehdr* header = GetHeader();
+ return header ? header->e_phnum : 0;
+}
+
+bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) {
+ for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) {
+ const Phdr* program = GetProgramHeader(i);
+ if (program->p_type != PT_LOAD)
+ continue;
+
+ size_t offset_in_segment = virtual_address - program->p_vaddr;
+ if (virtual_address >= program->p_vaddr &&
+ offset_in_segment < program->p_filesz) {
+ const void* data =
+ content_.GetData(program->p_offset + offset_in_segment, length);
+ if (data) {
+ memcpy(buffer, data, length);
+ return true;
+ }
+ }
+ }
+
+ /* fallback: if available, read from /proc/<pid>/mem */
+ if (proc_mem_fd_ != -1) {
+ off_t offset = virtual_address;
+ ssize_t r = pread(proc_mem_fd_, buffer, length, offset);
+ if (r < ssize_t(length)) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
+ElfCoreDump::Note ElfCoreDump::GetFirstNote() const {
+ MemoryRange note_content;
+ const Phdr* program_header = GetFirstProgramHeaderOfType(PT_NOTE);
+ if (program_header) {
+ note_content = content_.Subrange(program_header->p_offset,
+ program_header->p_filesz);
+ }
+ return Note(note_content);
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/elf_core_dump.h b/contrib/libs/breakpad/src/common/linux/elf_core_dump.h
new file mode 100644
index 0000000000..c8117a0e26
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elf_core_dump.h
@@ -0,0 +1,157 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// elf_core_dump.h: Define the google_breakpad::ElfCoreDump class, which
+// encapsulates an ELF core dump file mapped into memory.
+
+#ifndef COMMON_LINUX_ELF_CORE_DUMP_H_
+#define COMMON_LINUX_ELF_CORE_DUMP_H_
+
+#include <elf.h>
+#include <limits.h>
+#include <link.h>
+#include <stddef.h>
+
+#include "common/memory_range.h"
+
+namespace google_breakpad {
+
+// A class encapsulating an ELF core dump file mapped into memory, which
+// provides methods for accessing program headers and the note section.
+class ElfCoreDump {
+ public:
+ // ELF types based on the native word size.
+ typedef ElfW(Ehdr) Ehdr;
+ typedef ElfW(Nhdr) Nhdr;
+ typedef ElfW(Phdr) Phdr;
+ typedef ElfW(Word) Word;
+ typedef ElfW(Addr) Addr;
+#if ULONG_MAX == 0xffffffff
+ static const int kClass = ELFCLASS32;
+#elif ULONG_MAX == 0xffffffffffffffff
+ static const int kClass = ELFCLASS64;
+#else
+#error "Unsupported word size for ElfCoreDump."
+#endif
+
+ // A class encapsulating the note content in a core dump, which provides
+ // methods for accessing the name and description of a note.
+ class Note {
+ public:
+ Note();
+
+ // Constructor that takes the note content from |content|.
+ explicit Note(const MemoryRange& content);
+
+ // Returns true if this note is valid, i,e. a note header is found in
+ // |content_|, or false otherwise.
+ bool IsValid() const;
+
+ // Returns the note header, or NULL if no note header is found in
+ // |content_|.
+ const Nhdr* GetHeader() const;
+
+ // Returns the note type, or 0 if no note header is found in |content_|.
+ Word GetType() const;
+
+ // Returns a memory range covering the note name, or an empty range
+ // if no valid note name is found in |content_|.
+ MemoryRange GetName() const;
+
+ // Returns a memory range covering the note description, or an empty
+ // range if no valid note description is found in |content_|.
+ MemoryRange GetDescription() const;
+
+ // Returns the note following this note, or an empty note if no valid
+ // note is found after this note.
+ Note GetNextNote() const;
+
+ private:
+ // Returns the size in bytes round up to the word alignment, specified
+ // for the note section, of a given size in bytes.
+ static size_t AlignedSize(size_t size);
+
+ // Note content.
+ MemoryRange content_;
+ };
+
+ ElfCoreDump();
+
+ // Constructor that takes the core dump content from |content|.
+ explicit ElfCoreDump(const MemoryRange& content);
+
+ ~ElfCoreDump();
+
+ // Sets the core dump content to |content|.
+ void SetContent(const MemoryRange& content);
+
+ // Returns true if a valid ELF header in the core dump, or false otherwise.
+ bool IsValid() const;
+
+ // Returns the ELF header in the core dump, or NULL if no ELF header
+ // is found in |content_|.
+ const Ehdr* GetHeader() const;
+
+ // Returns the |index|-th program header in the core dump, or NULL if no
+ // ELF header is found in |content_| or |index| is out of bounds.
+ const Phdr* GetProgramHeader(unsigned index) const;
+
+ // Returns the first program header of |type| in the core dump, or NULL if
+ // no ELF header is found in |content_| or no program header of |type| is
+ // found.
+ const Phdr* GetFirstProgramHeaderOfType(Word type) const;
+
+ // Returns the number of program headers in the core dump, or 0 if no
+ // ELF header is found in |content_|.
+ unsigned GetProgramHeaderCount() const;
+
+ // Copies |length| bytes of data starting at |virtual_address| in the core
+ // dump to |buffer|. |buffer| should be a valid pointer to a buffer of at
+ // least |length| bytes. Returns true if the data to be copied is found in
+ // the core dump, or false otherwise.
+ bool CopyData(void* buffer, Addr virtual_address, size_t length);
+
+ // Returns the first note found in the note section of the core dump, or
+ // an empty note if no note is found.
+ Note GetFirstNote() const;
+
+ // Sets the mem fd.
+ void SetProcMem(const int fd);
+
+ private:
+ // Core dump content.
+ MemoryRange content_;
+
+ // Descriptor for /proc/<pid>/mem.
+ int proc_mem_fd_;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_ELF_CORE_DUMP_H_
diff --git a/contrib/libs/breakpad/src/common/linux/elf_gnu_compat.h b/contrib/libs/breakpad/src/common/linux/elf_gnu_compat.h
new file mode 100644
index 0000000000..0a3dfedb57
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elf_gnu_compat.h
@@ -0,0 +1,51 @@
+// -*- mode: C++ -*-
+
+// Copyright (c) 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Original author: Lei Zhang <thestig@google.com>
+
+// elf_gnu_compat.h: #defines unique to glibc's elf.h.
+
+#ifndef COMMON_LINUX_ELF_GNU_COMPAT_H_
+#define COMMON_LINUX_ELF_GNU_COMPAT_H_
+
+#include <elf.h>
+
+// A note type on GNU systems corresponding to the .note.gnu.build-id section.
+#ifndef NT_GNU_BUILD_ID
+#define NT_GNU_BUILD_ID 3
+#endif
+
+// Newer Linux systems offer this.
+#ifndef NT_SIGINFO
+#define NT_SIGINFO 0x53494749
+#endif
+
+#endif // COMMON_LINUX_ELF_GNU_COMPAT_H_
diff --git a/contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.cc b/contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.cc
new file mode 100644
index 0000000000..81e985a722
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.cc
@@ -0,0 +1,178 @@
+// -*- mode: c++ -*-
+
+// Copyright (c) 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
+
+#include "common/linux/elf_symbols_to_module.h"
+
+#include <cxxabi.h>
+#include <elf.h>
+#include <string.h>
+
+#include "common/byte_cursor.h"
+#include "common/module.h"
+
+namespace google_breakpad {
+
+class ELFSymbolIterator {
+public:
+ // The contents of an ELF symbol, adjusted for the host's endianness,
+ // word size, and so on. Corresponds to the data in Elf32_Sym / Elf64_Sym.
+ struct Symbol {
+ // True if this iterator has reached the end of the symbol array. When
+ // this is set, the other members of this structure are not valid.
+ bool at_end;
+
+ // The number of this symbol within the list.
+ size_t index;
+
+ // The current symbol's name offset. This is the offset within the
+ // string table.
+ size_t name_offset;
+
+ // The current symbol's value, size, info and shndx fields.
+ uint64_t value;
+ uint64_t size;
+ unsigned char info;
+ uint16_t shndx;
+ };
+
+ // Create an ELFSymbolIterator walking the symbols in BUFFER. Treat the
+ // symbols as big-endian if BIG_ENDIAN is true, as little-endian
+ // otherwise. Assume each symbol has a 'value' field whose size is
+ // VALUE_SIZE.
+ //
+ ELFSymbolIterator(const ByteBuffer* buffer, bool big_endian,
+ size_t value_size)
+ : value_size_(value_size), cursor_(buffer, big_endian) {
+ // Actually, weird sizes could be handled just fine, but they're
+ // probably mistakes --- expressed in bits, say.
+ assert(value_size == 4 || value_size == 8);
+ symbol_.index = 0;
+ Fetch();
+ }
+
+ // Move to the next symbol. This function's behavior is undefined if
+ // at_end() is true when it is called.
+ ELFSymbolIterator& operator++() { Fetch(); symbol_.index++; return *this; }
+
+ // Dereferencing this iterator produces a reference to an Symbol structure
+ // that holds the current symbol's values. The symbol is owned by this
+ // SymbolIterator, and will be invalidated at the next call to operator++.
+ const Symbol& operator*() const { return symbol_; }
+ const Symbol* operator->() const { return &symbol_; }
+
+private:
+ // Read the symbol at cursor_, and set symbol_ appropriately.
+ void Fetch() {
+ // Elf32_Sym and Elf64_Sym have different layouts.
+ unsigned char other;
+ if (value_size_ == 4) {
+ // Elf32_Sym
+ cursor_
+ .Read(4, false, &symbol_.name_offset)
+ .Read(4, false, &symbol_.value)
+ .Read(4, false, &symbol_.size)
+ .Read(1, false, &symbol_.info)
+ .Read(1, false, &other)
+ .Read(2, false, &symbol_.shndx);
+ } else {
+ // Elf64_Sym
+ cursor_
+ .Read(4, false, &symbol_.name_offset)
+ .Read(1, false, &symbol_.info)
+ .Read(1, false, &other)
+ .Read(2, false, &symbol_.shndx)
+ .Read(8, false, &symbol_.value)
+ .Read(8, false, &symbol_.size);
+ }
+ symbol_.at_end = !cursor_;
+ }
+
+ // The size of symbols' value field, in bytes.
+ size_t value_size_;
+
+ // A byte cursor traversing buffer_.
+ ByteCursor cursor_;
+
+ // Values for the symbol this iterator refers to.
+ Symbol symbol_;
+};
+
+const char* SymbolString(ptrdiff_t offset, ByteBuffer& strings) {
+ if (offset < 0 || (size_t) offset >= strings.Size()) {
+ // Return the null string.
+ offset = 0;
+ }
+ return reinterpret_cast<const char*>(strings.start + offset);
+}
+
+bool ELFSymbolsToModule(const uint8_t* symtab_section,
+ size_t symtab_size,
+ const uint8_t* string_section,
+ size_t string_size,
+ const bool big_endian,
+ size_t value_size,
+ Module* module) {
+ ByteBuffer symbols(symtab_section, symtab_size);
+ // Ensure that the string section is null-terminated.
+ if (string_section[string_size - 1] != '\0') {
+ const void* null_terminator = memrchr(string_section, '\0', string_size);
+ string_size = reinterpret_cast<const uint8_t*>(null_terminator)
+ - string_section;
+ }
+ ByteBuffer strings(string_section, string_size);
+
+ // The iterator walking the symbol table.
+ ELFSymbolIterator iterator(&symbols, big_endian, value_size);
+
+ while(!iterator->at_end) {
+ if (ELF32_ST_TYPE(iterator->info) == STT_FUNC &&
+ iterator->shndx != SHN_UNDEF) {
+ Module::Extern* ext = new Module::Extern(iterator->value);
+ ext->name = SymbolString(iterator->name_offset, strings);
+#if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle.
+ int status = 0;
+ char* demangled =
+ abi::__cxa_demangle(ext->name.c_str(), NULL, NULL, &status);
+ if (demangled) {
+ if (status == 0)
+ ext->name = demangled;
+ free(demangled);
+ }
+#endif
+ module->AddExtern(ext);
+ }
+ ++iterator;
+ }
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.h b/contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.h
new file mode 100644
index 0000000000..861f725297
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elf_symbols_to_module.h
@@ -0,0 +1,58 @@
+// -*- mode: c++ -*-
+
+// Copyright (c) 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
+
+// elf_symbols_to_module.h: Exposes ELFSymbolsToModule, a function
+// for reading ELF symbol tables and inserting exported symbol names
+// into a google_breakpad::Module as Extern definitions.
+
+#ifndef BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_
+#define BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace google_breakpad {
+
+class Module;
+
+bool ELFSymbolsToModule(const uint8_t* symtab_section,
+ size_t symtab_size,
+ const uint8_t* string_section,
+ size_t string_size,
+ const bool big_endian,
+ size_t value_size,
+ Module* module);
+
+} // namespace google_breakpad
+
+
+#endif // BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_
diff --git a/contrib/libs/breakpad/src/common/linux/elfutils-inl.h b/contrib/libs/breakpad/src/common/linux/elfutils-inl.h
new file mode 100644
index 0000000000..e56b37a9f5
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elfutils-inl.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_ELFUTILS_INL_H__
+#define COMMON_LINUX_ELFUTILS_INL_H__
+
+#include "common/linux/linux_libc_support.h"
+#include "elfutils.h"
+
+namespace google_breakpad {
+
+template<typename ElfClass, typename T>
+const T* GetOffset(const typename ElfClass::Ehdr* elf_header,
+ typename ElfClass::Off offset) {
+ return reinterpret_cast<const T*>(reinterpret_cast<uintptr_t>(elf_header) +
+ offset);
+}
+
+template<typename ElfClass>
+const typename ElfClass::Shdr* FindElfSectionByName(
+ const char* name,
+ typename ElfClass::Word section_type,
+ const typename ElfClass::Shdr* sections,
+ const char* section_names,
+ const char* names_end,
+ int nsection) {
+ assert(name != NULL);
+ assert(sections != NULL);
+ assert(nsection > 0);
+
+ int name_len = my_strlen(name);
+ if (name_len == 0)
+ return NULL;
+
+ for (int i = 0; i < nsection; ++i) {
+ const char* section_name = section_names + sections[i].sh_name;
+ if (sections[i].sh_type == section_type &&
+ names_end - section_name >= name_len + 1 &&
+ my_strcmp(name, section_name) == 0) {
+ return sections + i;
+ }
+ }
+ return NULL;
+}
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_ELFUTILS_INL_H__
diff --git a/contrib/libs/breakpad/src/common/linux/elfutils.cc b/contrib/libs/breakpad/src/common/linux/elfutils.cc
new file mode 100644
index 0000000000..aa95357a3a
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elfutils.cc
@@ -0,0 +1,243 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/linux/elfutils.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "common/linux/linux_libc_support.h"
+#include "common/linux/elfutils-inl.h"
+
+namespace google_breakpad {
+
+namespace {
+
+template<typename ElfClass>
+void FindElfClassSection(const char* elf_base,
+ const char* section_name,
+ typename ElfClass::Word section_type,
+ const void** section_start,
+ size_t* section_size) {
+ typedef typename ElfClass::Ehdr Ehdr;
+ typedef typename ElfClass::Shdr Shdr;
+
+ assert(elf_base);
+ assert(section_start);
+ assert(section_size);
+
+ assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
+
+ const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
+ assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
+
+ if (elf_header->e_shoff == 0) {
+ *section_start = NULL;
+ *section_size = 0;
+ return;
+ }
+
+ const Shdr* sections =
+ GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
+ const Shdr* section_names = sections + elf_header->e_shstrndx;
+ const char* names =
+ GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
+ const char* names_end = names + section_names->sh_size;
+
+ const Shdr* section =
+ FindElfSectionByName<ElfClass>(section_name, section_type,
+ sections, names, names_end,
+ elf_header->e_shnum);
+
+ if (section != NULL && section->sh_size > 0) {
+ *section_start = elf_base + section->sh_offset;
+ *section_size = section->sh_size;
+ }
+}
+
+template<typename ElfClass>
+void FindElfClassSegment(const char* elf_base,
+ typename ElfClass::Word segment_type,
+ wasteful_vector<ElfSegment>* segments) {
+ typedef typename ElfClass::Ehdr Ehdr;
+ typedef typename ElfClass::Phdr Phdr;
+
+ assert(elf_base);
+ assert(segments);
+
+ assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
+
+ const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
+ assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
+
+ const Phdr* phdrs =
+ GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff);
+
+ for (int i = 0; i < elf_header->e_phnum; ++i) {
+ if (phdrs[i].p_type == segment_type) {
+ ElfSegment seg = {};
+ seg.start = elf_base + phdrs[i].p_offset;
+ seg.size = phdrs[i].p_filesz;
+ segments->push_back(seg);
+ }
+ }
+}
+
+} // namespace
+
+bool IsValidElf(const void* elf_base) {
+ return my_strncmp(reinterpret_cast<const char*>(elf_base),
+ ELFMAG, SELFMAG) == 0;
+}
+
+int ElfClass(const void* elf_base) {
+ const ElfW(Ehdr)* elf_header =
+ reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
+
+ return elf_header->e_ident[EI_CLASS];
+}
+
+bool FindElfSection(const void* elf_mapped_base,
+ const char* section_name,
+ uint32_t section_type,
+ const void** section_start,
+ size_t* section_size) {
+ assert(elf_mapped_base);
+ assert(section_start);
+ assert(section_size);
+
+ *section_start = NULL;
+ *section_size = 0;
+
+ if (!IsValidElf(elf_mapped_base))
+ return false;
+
+ int cls = ElfClass(elf_mapped_base);
+ const char* elf_base =
+ static_cast<const char*>(elf_mapped_base);
+
+ if (cls == ELFCLASS32) {
+ FindElfClassSection<ElfClass32>(elf_base, section_name, section_type,
+ section_start, section_size);
+ return *section_start != NULL;
+ } else if (cls == ELFCLASS64) {
+ FindElfClassSection<ElfClass64>(elf_base, section_name, section_type,
+ section_start, section_size);
+ return *section_start != NULL;
+ }
+
+ return false;
+}
+
+bool FindElfSegments(const void* elf_mapped_base,
+ uint32_t segment_type,
+ wasteful_vector<ElfSegment>* segments) {
+ assert(elf_mapped_base);
+ assert(segments);
+
+ if (!IsValidElf(elf_mapped_base))
+ return false;
+
+ int cls = ElfClass(elf_mapped_base);
+ const char* elf_base =
+ static_cast<const char*>(elf_mapped_base);
+
+ if (cls == ELFCLASS32) {
+ FindElfClassSegment<ElfClass32>(elf_base, segment_type, segments);
+ return true;
+ } else if (cls == ELFCLASS64) {
+ FindElfClassSegment<ElfClass64>(elf_base, segment_type, segments);
+ return true;
+ }
+
+ return false;
+}
+
+template <typename ElfClass>
+bool FindElfSoNameFromDynamicSection(const void* section_start,
+ size_t section_size,
+ const void* dynstr_start,
+ size_t dynstr_size,
+ char* soname,
+ size_t soname_size) {
+ typedef typename ElfClass::Dyn Dyn;
+
+ auto* dynamic = static_cast<const Dyn*>(section_start);
+ size_t dcount = section_size / sizeof(Dyn);
+ for (const Dyn* dyn = dynamic; dyn < dynamic + dcount; ++dyn) {
+ if (dyn->d_tag == DT_SONAME) {
+ const char* dynstr = static_cast<const char*>(dynstr_start);
+ if (dyn->d_un.d_val >= dynstr_size) {
+ // Beyond the end of the dynstr section
+ return false;
+ }
+ const char* str = dynstr + dyn->d_un.d_val;
+ const size_t maxsize = dynstr_size - dyn->d_un.d_val;
+ my_strlcpy(soname, str, maxsize < soname_size ? maxsize : soname_size);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ElfFileSoNameFromMappedFile(const void* elf_base,
+ char* soname,
+ size_t soname_size) {
+ if (!IsValidElf(elf_base)) {
+ // Not ELF
+ return false;
+ }
+
+ const void* segment_start;
+ size_t segment_size;
+ if (!FindElfSection(elf_base, ".dynamic", SHT_DYNAMIC, &segment_start,
+ &segment_size)) {
+ // No dynamic section
+ return false;
+ }
+
+ const void* dynstr_start;
+ size_t dynstr_size;
+ if (!FindElfSection(elf_base, ".dynstr", SHT_STRTAB, &dynstr_start,
+ &dynstr_size)) {
+ // No dynstr section
+ return false;
+ }
+
+ int cls = ElfClass(elf_base);
+ return cls == ELFCLASS32 ? FindElfSoNameFromDynamicSection<ElfClass32>(
+ segment_start, segment_size, dynstr_start,
+ dynstr_size, soname, soname_size)
+ : FindElfSoNameFromDynamicSection<ElfClass64>(
+ segment_start, segment_size, dynstr_start,
+ dynstr_size, soname, soname_size);
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/elfutils.h b/contrib/libs/breakpad/src/common/linux/elfutils.h
new file mode 100644
index 0000000000..ec5872a4f3
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/elfutils.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// elfutils.h: Utilities for dealing with ELF files.
+//
+
+#ifndef COMMON_LINUX_ELFUTILS_H_
+#define COMMON_LINUX_ELFUTILS_H_
+
+#include <elf.h>
+#include <link.h>
+#include <stdint.h>
+
+#include "common/memory_allocator.h"
+
+namespace google_breakpad {
+
+// Traits classes so consumers can write templatized code to deal
+// with specific ELF bits.
+struct ElfClass32 {
+ typedef Elf32_Addr Addr;
+ typedef Elf32_Dyn Dyn;
+ typedef Elf32_Ehdr Ehdr;
+ typedef Elf32_Nhdr Nhdr;
+ typedef Elf32_Phdr Phdr;
+ typedef Elf32_Shdr Shdr;
+ typedef Elf32_Half Half;
+ typedef Elf32_Off Off;
+ typedef Elf32_Sym Sym;
+ typedef Elf32_Word Word;
+
+ static const int kClass = ELFCLASS32;
+ static const uint16_t kMachine = EM_386;
+ static const size_t kAddrSize = sizeof(Elf32_Addr);
+ static constexpr const char* kMachineName = "x86";
+};
+
+struct ElfClass64 {
+ typedef Elf64_Addr Addr;
+ typedef Elf64_Dyn Dyn;
+ typedef Elf64_Ehdr Ehdr;
+ typedef Elf64_Nhdr Nhdr;
+ typedef Elf64_Phdr Phdr;
+ typedef Elf64_Shdr Shdr;
+ typedef Elf64_Half Half;
+ typedef Elf64_Off Off;
+ typedef Elf64_Sym Sym;
+ typedef Elf64_Word Word;
+
+ static const int kClass = ELFCLASS64;
+ static const uint16_t kMachine = EM_X86_64;
+ static const size_t kAddrSize = sizeof(Elf64_Addr);
+ static constexpr const char* kMachineName = "x86_64";
+};
+
+bool IsValidElf(const void* elf_header);
+int ElfClass(const void* elf_base);
+
+// Attempt to find a section named |section_name| of type |section_type|
+// in the ELF binary data at |elf_mapped_base|. On success, returns true
+// and sets |*section_start| to point to the start of the section data,
+// and |*section_size| to the size of the section's data.
+bool FindElfSection(const void* elf_mapped_base,
+ const char* section_name,
+ uint32_t section_type,
+ const void** section_start,
+ size_t* section_size);
+
+// Internal helper method, exposed for convenience for callers
+// that already have more info.
+template<typename ElfClass>
+const typename ElfClass::Shdr*
+FindElfSectionByName(const char* name,
+ typename ElfClass::Word section_type,
+ const typename ElfClass::Shdr* sections,
+ const char* section_names,
+ const char* names_end,
+ int nsection);
+
+struct ElfSegment {
+ const void* start;
+ size_t size;
+};
+
+// Attempt to find all segments of type |segment_type| in the ELF
+// binary data at |elf_mapped_base|. On success, returns true and fills
+// |*segments| with a list of segments of the given type.
+bool FindElfSegments(const void* elf_mapped_base,
+ uint32_t segment_type,
+ wasteful_vector<ElfSegment>* segments);
+
+// Convert an offset from an Elf header into a pointer to the mapped
+// address in the current process. Takes an extra template parameter
+// to specify the return type to avoid having to dynamic_cast the
+// result.
+template<typename ElfClass, typename T>
+const T*
+GetOffset(const typename ElfClass::Ehdr* elf_header,
+ typename ElfClass::Off offset);
+
+// Read the value of DT_SONAME from the elf file mapped at |elf_base|. Returns
+// true and fills |soname| with the result if found.
+bool ElfFileSoNameFromMappedFile(const void* elf_base,
+ char* soname,
+ size_t soname_size);
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_ELFUTILS_H_
diff --git a/contrib/libs/breakpad/src/common/linux/file_id.cc b/contrib/libs/breakpad/src/common/linux/file_id.cc
new file mode 100644
index 0000000000..b483eb5c02
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/file_id.cc
@@ -0,0 +1,203 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// file_id.cc: Return a unique identifier for a file
+//
+// See file_id.h for documentation
+//
+
+#include "common/linux/file_id.h"
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+
+#include "common/linux/elf_gnu_compat.h"
+#include "common/linux/elfutils.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/linux/memory_mapped_file.h"
+#include "common/using_std_string.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+namespace elf {
+
+// Used in a few places for backwards-compatibility.
+const size_t kMDGUIDSize = sizeof(MDGUID);
+
+FileID::FileID(const char* path) : path_(path) {}
+
+// ELF note name and desc are 32-bits word padded.
+#define NOTE_PADDING(a) ((a + 3) & ~3)
+
+// These functions are also used inside the crashed process, so be safe
+// and use the syscall/libc wrappers instead of direct syscalls or libc.
+
+static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length,
+ wasteful_vector<uint8_t>& identifier) {
+ static_assert(sizeof(ElfClass32::Nhdr) == sizeof(ElfClass64::Nhdr),
+ "Elf32_Nhdr and Elf64_Nhdr should be the same");
+ typedef typename ElfClass32::Nhdr Nhdr;
+
+ const void* section_end = reinterpret_cast<const char*>(section) + length;
+ const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section);
+ while (reinterpret_cast<const void*>(note_header) < section_end) {
+ if (note_header->n_type == NT_GNU_BUILD_ID)
+ break;
+ note_header = reinterpret_cast<const Nhdr*>(
+ reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
+ NOTE_PADDING(note_header->n_namesz) +
+ NOTE_PADDING(note_header->n_descsz));
+ }
+ if (reinterpret_cast<const void*>(note_header) >= section_end ||
+ note_header->n_descsz == 0) {
+ return false;
+ }
+
+ const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) +
+ sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
+ identifier.insert(identifier.end(),
+ build_id,
+ build_id + note_header->n_descsz);
+
+ return true;
+}
+
+// Attempt to locate a .note.gnu.build-id section in an ELF binary
+// and copy it into |identifier|.
+static bool FindElfBuildIDNote(const void* elf_mapped_base,
+ wasteful_vector<uint8_t>& identifier) {
+ PageAllocator allocator;
+ // lld normally creates 2 PT_NOTEs, gold normally creates 1.
+ auto_wasteful_vector<ElfSegment, 2> segs(&allocator);
+ if (FindElfSegments(elf_mapped_base, PT_NOTE, &segs)) {
+ for (ElfSegment& seg : segs) {
+ if (ElfClassBuildIDNoteIdentifier(seg.start, seg.size, identifier)) {
+ return true;
+ }
+ }
+ }
+
+ void* note_section;
+ size_t note_size;
+ if (FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
+ (const void**)&note_section, &note_size)) {
+ return ElfClassBuildIDNoteIdentifier(note_section, note_size, identifier);
+ }
+
+ return false;
+}
+
+// Attempt to locate the .text section of an ELF binary and generate
+// a simple hash by XORing the first page worth of bytes into |identifier|.
+static bool HashElfTextSection(const void* elf_mapped_base,
+ wasteful_vector<uint8_t>& identifier) {
+ identifier.resize(kMDGUIDSize);
+
+ void* text_section;
+ size_t text_size;
+ if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
+ (const void**)&text_section, &text_size) ||
+ text_size == 0) {
+ return false;
+ }
+
+ // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
+ // function backwards-compatible.
+ my_memset(&identifier[0], 0, kMDGUIDSize);
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
+ const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096));
+ while (ptr < ptr_end) {
+ for (unsigned i = 0; i < kMDGUIDSize; i++)
+ identifier[i] ^= ptr[i];
+ ptr += kMDGUIDSize;
+ }
+ return true;
+}
+
+// static
+bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
+ wasteful_vector<uint8_t>& identifier) {
+ // Look for a build id note first.
+ if (FindElfBuildIDNote(base, identifier))
+ return true;
+
+ // Fall back on hashing the first page of the text section.
+ return HashElfTextSection(base, identifier);
+}
+
+bool FileID::ElfFileIdentifier(wasteful_vector<uint8_t>& identifier) {
+ MemoryMappedFile mapped_file(path_.c_str(), 0);
+ if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
+ return false;
+
+ return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
+}
+
+// These three functions are not ever called in an unsafe context, so it's OK
+// to allocate memory and use libc.
+static string bytes_to_hex_string(const uint8_t* bytes, size_t count) {
+ string result;
+ for (unsigned int idx = 0; idx < count; ++idx) {
+ char buf[3];
+ snprintf(buf, sizeof(buf), "%02X", bytes[idx]);
+ result.append(buf);
+ }
+ return result;
+}
+
+// static
+string FileID::ConvertIdentifierToUUIDString(
+ const wasteful_vector<uint8_t>& identifier) {
+ uint8_t identifier_swapped[kMDGUIDSize] = { 0 };
+
+ // Endian-ness swap to match dump processor expectation.
+ memcpy(identifier_swapped, &identifier[0],
+ std::min(kMDGUIDSize, identifier.size()));
+ uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
+ *data1 = htonl(*data1);
+ uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
+ *data2 = htons(*data2);
+ uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
+ *data3 = htons(*data3);
+
+ return bytes_to_hex_string(identifier_swapped, kMDGUIDSize);
+}
+
+// static
+string FileID::ConvertIdentifierToString(
+ const wasteful_vector<uint8_t>& identifier) {
+ return bytes_to_hex_string(&identifier[0], identifier.size());
+}
+
+} // elf
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/file_id.h b/contrib/libs/breakpad/src/common/linux/file_id.h
new file mode 100644
index 0000000000..8556a2e5ae
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/file_id.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// file_id.h: Return a unique identifier for a file
+//
+
+#ifndef COMMON_LINUX_FILE_ID_H__
+#define COMMON_LINUX_FILE_ID_H__
+
+#include <limits.h>
+#include <string>
+
+#include "common/linux/guid_creator.h"
+#include "common/memory_allocator.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+namespace elf {
+
+// GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes,
+// so this is enough to fit that, which most binaries will use.
+// This is just a sensible default for auto_wasteful_vector so most
+// callers can get away with stack allocation.
+static const size_t kDefaultBuildIdSize = 20;
+
+class FileID {
+ public:
+ explicit FileID(const char* path);
+ ~FileID() {}
+
+ // Load the identifier for the elf file path specified in the constructor into
+ // |identifier|.
+ //
+ // The current implementation will look for a .note.gnu.build-id
+ // section and use that as the file id, otherwise it falls back to
+ // XORing the first 4096 bytes of the .text section to generate an identifier.
+ bool ElfFileIdentifier(wasteful_vector<uint8_t>& identifier);
+
+ // Load the identifier for the elf file mapped into memory at |base| into
+ // |identifier|. Return false if the identifier could not be created for this
+ // file.
+ static bool ElfFileIdentifierFromMappedFile(
+ const void* base,
+ wasteful_vector<uint8_t>& identifier);
+
+ // Convert the |identifier| data to a string. The string will
+ // be formatted as a UUID in all uppercase without dashes.
+ // (e.g., 22F065BBFC9C49F780FE26A7CEBD7BCE).
+ static string ConvertIdentifierToUUIDString(
+ const wasteful_vector<uint8_t>& identifier);
+
+ // Convert the entire |identifier| data to a hex string.
+ static string ConvertIdentifierToString(
+ const wasteful_vector<uint8_t>& identifier);
+
+ private:
+ // Storage for the path specified
+ string path_;
+};
+
+} // namespace elf
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_FILE_ID_H__
diff --git a/contrib/libs/breakpad/src/common/linux/guid_creator.cc b/contrib/libs/breakpad/src/common/linux/guid_creator.cc
new file mode 100644
index 0000000000..6374063825
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/guid_creator.cc
@@ -0,0 +1,189 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/guid_creator.h"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+
+#if defined(HAVE_SYS_RANDOM_H)
+#include <sys/random.h>
+#endif
+
+//
+// GUIDGenerator
+//
+// This class is used to generate random GUID.
+// Currently use random number to generate a GUID since Linux has
+// no native GUID generator. This should be OK since we don't expect
+// crash to happen very offen.
+//
+class GUIDGenerator {
+ public:
+ static uint32_t BytesToUInt32(const uint8_t bytes[]) {
+ return ((uint32_t) bytes[0]
+ | ((uint32_t) bytes[1] << 8)
+ | ((uint32_t) bytes[2] << 16)
+ | ((uint32_t) bytes[3] << 24));
+ }
+
+ static void UInt32ToBytes(uint8_t bytes[], uint32_t n) {
+ bytes[0] = n & 0xff;
+ bytes[1] = (n >> 8) & 0xff;
+ bytes[2] = (n >> 16) & 0xff;
+ bytes[3] = (n >> 24) & 0xff;
+ }
+
+ static bool CreateGUID(GUID *guid) {
+#if defined(HAVE_ARC4RANDOM) // Android, BSD, ...
+ CreateGuidFromArc4Random(guid);
+#else // Linux
+ bool success = false;
+
+#if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM)
+ success = CreateGUIDFromGetrandom(guid);
+#endif // HAVE_SYS_RANDOM_H && HAVE_GETRANDOM
+ if (!success) {
+ success = CreateGUIDFromDevUrandom(guid);
+ }
+
+ if (!success) {
+ CreateGUIDFromRand(guid);
+ success = true;
+ }
+#endif
+
+ // Put in the version according to RFC 4122.
+ guid->data3 &= 0x0fff;
+ guid->data3 |= 0x4000;
+
+ // Put in the variant according to RFC 4122.
+ guid->data4[0] &= 0x3f;
+ guid->data4[0] |= 0x80;
+
+ return true;
+ }
+
+ private:
+#ifdef HAVE_ARC4RANDOM
+ static void CreateGuidFromArc4Random(GUID *guid) {
+ char *buf = reinterpret_cast<char*>(guid);
+
+ for (size_t i = 0; i < sizeof(GUID); i += sizeof(uint32_t)) {
+ uint32_t random_data = arc4random();
+
+ memcpy(buf + i, &random_data, sizeof(uint32_t));
+ }
+ }
+#else
+ static void InitOnce() {
+ pthread_once(&once_control, &InitOnceImpl);
+ }
+
+ static void InitOnceImpl() {
+ // time(NULL) is a very poor seed, so lacking anything better mix an
+ // address into it. We drop the four rightmost bits as they're likely to
+ // be 0 on almost all architectures.
+ srand(time(NULL) | ((uintptr_t)&once_control >> 4));
+ }
+
+ static pthread_once_t once_control;
+
+#if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM)
+ static bool CreateGUIDFromGetrandom(GUID *guid) {
+ char *buf = reinterpret_cast<char*>(guid);
+ int read_bytes = getrandom(buf, sizeof(GUID), GRND_NONBLOCK);
+
+ return (read_bytes == static_cast<int>(sizeof(GUID)));
+ }
+#endif // HAVE_SYS_RANDOM_H && HAVE_GETRANDOM
+
+ // Populate the GUID using random bytes read from /dev/urandom, returns false
+ // if the GUID wasn't fully populated with random data.
+ static bool CreateGUIDFromDevUrandom(GUID *guid) {
+ char *buf = reinterpret_cast<char*>(guid);
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+
+ if (fd == -1) {
+ return false;
+ }
+
+ ssize_t read_bytes = HANDLE_EINTR(read(fd, buf, sizeof(GUID)));
+ close(fd);
+
+ return (read_bytes == static_cast<ssize_t>(sizeof(GUID)));
+ }
+
+ // Populate the GUID using a stream of random bytes obtained from rand().
+ static void CreateGUIDFromRand(GUID *guid) {
+ char *buf = reinterpret_cast<char*>(guid);
+
+ InitOnce();
+
+ for (size_t i = 0; i < sizeof(GUID); i++) {
+ buf[i] = rand();
+ }
+ }
+#endif
+};
+
+#ifndef HAVE_ARC4RANDOM
+pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT;
+#endif
+
+bool CreateGUID(GUID *guid) {
+ return GUIDGenerator::CreateGUID(guid);
+}
+
+// Parse guid to string.
+bool GUIDToString(const GUID *guid, char *buf, int buf_len) {
+ // Should allow more space the the max length of GUID.
+ assert(buf_len > kGUIDStringLength);
+ int num = snprintf(buf, buf_len, kGUIDFormatString,
+ guid->data1, guid->data2, guid->data3,
+ GUIDGenerator::BytesToUInt32(&(guid->data4[0])),
+ GUIDGenerator::BytesToUInt32(&(guid->data4[4])));
+ if (num != kGUIDStringLength)
+ return false;
+
+ buf[num] = '\0';
+ return true;
+}
diff --git a/contrib/libs/breakpad/src/common/linux/guid_creator.h b/contrib/libs/breakpad/src/common/linux/guid_creator.h
new file mode 100644
index 0000000000..c86d856c4d
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/guid_creator.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_GUID_CREATOR_H__
+#define COMMON_LINUX_GUID_CREATOR_H__
+
+#include "google_breakpad/common/minidump_format.h"
+
+typedef MDGUID GUID;
+
+// Format string for parsing GUID.
+#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x"
+// Length of GUID string. Don't count the ending '\0'.
+#define kGUIDStringLength 36
+
+// Create a guid.
+bool CreateGUID(GUID *guid);
+
+// Get the string from guid.
+bool GUIDToString(const GUID *guid, char *buf, int buf_len);
+
+#endif
diff --git a/contrib/libs/breakpad/src/common/linux/http_upload.cc b/contrib/libs/breakpad/src/common/linux/http_upload.cc
new file mode 100644
index 0000000000..ace12b84e1
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/http_upload.cc
@@ -0,0 +1,230 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/linux/http_upload.h"
+
+#include <assert.h>
+#include <dlfcn.h>
+#include "third_party/curl/curl.h"
+
+namespace {
+
+// Callback to get the response data from server.
+static size_t WriteCallback(void* ptr, size_t size,
+ size_t nmemb, void* userp) {
+ if (!userp)
+ return 0;
+
+ string* response = reinterpret_cast<string*>(userp);
+ size_t real_size = size * nmemb;
+ response->append(reinterpret_cast<char*>(ptr), real_size);
+ return real_size;
+}
+
+} // namespace
+
+namespace google_breakpad {
+
+static const char kUserAgent[] = "Breakpad/1.0 (Linux)";
+
+// static
+bool HTTPUpload::SendRequest(const string& url,
+ const map<string, string>& parameters,
+ const map<string, string>& files,
+ const string& proxy,
+ const string& proxy_user_pwd,
+ const string& ca_certificate_file,
+ string* response_body,
+ long* response_code,
+ string* error_description) {
+ if (response_code != NULL)
+ *response_code = 0;
+
+ if (!CheckParameters(parameters))
+ return false;
+
+ // We may have been linked statically; if curl_easy_init is in the
+ // current binary, no need to search for a dynamic version.
+ void* curl_lib = dlopen(NULL, RTLD_NOW);
+ if (!CheckCurlLib(curl_lib)) {
+ fprintf(stderr,
+ "Failed to open curl lib from binary, use libcurl.so instead\n");
+ dlerror(); // Clear dlerror before attempting to open libraries.
+ dlclose(curl_lib);
+ curl_lib = NULL;
+ }
+ if (!curl_lib) {
+ curl_lib = dlopen("libcurl.so", RTLD_NOW);
+ }
+ if (!curl_lib) {
+ if (error_description != NULL)
+ *error_description = dlerror();
+ curl_lib = dlopen("libcurl.so.4", RTLD_NOW);
+ }
+ if (!curl_lib) {
+ // Debian gives libcurl a different name when it is built against GnuTLS
+ // instead of OpenSSL.
+ curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_NOW);
+ }
+ if (!curl_lib) {
+ curl_lib = dlopen("libcurl.so.3", RTLD_NOW);
+ }
+ if (!curl_lib) {
+ return false;
+ }
+
+ CURL* (*curl_easy_init)(void);
+ *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init");
+ CURL* curl = (*curl_easy_init)();
+ if (error_description != NULL)
+ *error_description = "No Error";
+
+ if (!curl) {
+ dlclose(curl_lib);
+ return false;
+ }
+
+ CURLcode err_code = CURLE_OK;
+ CURLcode (*curl_easy_setopt)(CURL*, CURLoption, ...);
+ *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt");
+ (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str());
+ (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent);
+ // Support multithread by disabling timeout handling, would get SIGSEGV with
+ // Curl_resolv_timeout in stack trace otherwise.
+ // See https://curl.haxx.se/libcurl/c/threadsafe.html
+ (*curl_easy_setopt)(curl, CURLOPT_NOSIGNAL, 1);
+ // Set proxy information if necessary.
+ if (!proxy.empty())
+ (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str());
+ if (!proxy_user_pwd.empty())
+ (*curl_easy_setopt)(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str());
+
+ if (!ca_certificate_file.empty())
+ (*curl_easy_setopt)(curl, CURLOPT_CAINFO, ca_certificate_file.c_str());
+
+ struct curl_httppost* formpost = NULL;
+ struct curl_httppost* lastptr = NULL;
+ // Add form data.
+ CURLFORMcode (*curl_formadd)(struct curl_httppost**, struct curl_httppost**, ...);
+ *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd");
+ map<string, string>::const_iterator iter = parameters.begin();
+ for (; iter != parameters.end(); ++iter)
+ (*curl_formadd)(&formpost, &lastptr,
+ CURLFORM_COPYNAME, iter->first.c_str(),
+ CURLFORM_COPYCONTENTS, iter->second.c_str(),
+ CURLFORM_END);
+
+ // Add form files.
+ for (iter = files.begin(); iter != files.end(); ++iter) {
+ (*curl_formadd)(&formpost, &lastptr,
+ CURLFORM_COPYNAME, iter->first.c_str(),
+ CURLFORM_FILE, iter->second.c_str(),
+ CURLFORM_END);
+ }
+
+ (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost);
+
+ // Disable 100-continue header.
+ struct curl_slist* headerlist = NULL;
+ char buf[] = "Expect:";
+ struct curl_slist* (*curl_slist_append)(struct curl_slist*, const char*);
+ *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append");
+ headerlist = (*curl_slist_append)(headerlist, buf);
+ (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist);
+
+ if (response_body != NULL) {
+ (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+ (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA,
+ reinterpret_cast<void*>(response_body));
+ }
+
+ // Fail if 400+ is returned from the web server.
+ (*curl_easy_setopt)(curl, CURLOPT_FAILONERROR, 1);
+
+ CURLcode (*curl_easy_perform)(CURL*);
+ *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform");
+ err_code = (*curl_easy_perform)(curl);
+ if (response_code != NULL) {
+ CURLcode (*curl_easy_getinfo)(CURL*, CURLINFO, ...);
+ *(void**) (&curl_easy_getinfo) = dlsym(curl_lib, "curl_easy_getinfo");
+ (*curl_easy_getinfo)(curl, CURLINFO_RESPONSE_CODE, response_code);
+ }
+ const char* (*curl_easy_strerror)(CURLcode);
+ *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror");
+#ifndef NDEBUG
+ if (err_code != CURLE_OK)
+ fprintf(stderr, "Failed to send http request to %s, error: %s\n",
+ url.c_str(),
+ (*curl_easy_strerror)(err_code));
+#endif
+ if (error_description != NULL)
+ *error_description = (*curl_easy_strerror)(err_code);
+
+ void (*curl_easy_cleanup)(CURL*);
+ *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup");
+ (*curl_easy_cleanup)(curl);
+ if (formpost != NULL) {
+ void (*curl_formfree)(struct curl_httppost*);
+ *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree");
+ (*curl_formfree)(formpost);
+ }
+ if (headerlist != NULL) {
+ void (*curl_slist_free_all)(struct curl_slist*);
+ *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all");
+ (*curl_slist_free_all)(headerlist);
+ }
+ dlclose(curl_lib);
+ return err_code == CURLE_OK;
+}
+
+// static
+bool HTTPUpload::CheckCurlLib(void* curl_lib) {
+ return curl_lib &&
+ dlsym(curl_lib, "curl_easy_init") &&
+ dlsym(curl_lib, "curl_easy_setopt");
+}
+
+// static
+bool HTTPUpload::CheckParameters(const map<string, string>& parameters) {
+ for (map<string, string>::const_iterator pos = parameters.begin();
+ pos != parameters.end(); ++pos) {
+ const string& str = pos->first;
+ if (str.size() == 0)
+ return false; // disallow empty parameter names
+ for (unsigned int i = 0; i < str.size(); ++i) {
+ int c = str[i];
+ if (c < 32 || c == '"' || c > 127) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/http_upload.h b/contrib/libs/breakpad/src/common/linux/http_upload.h
new file mode 100644
index 0000000000..13f3d56cc8
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/http_upload.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST
+// request using libcurl. It currently supports requests that contain
+// a set of string parameters (key/value pairs), and a file to upload.
+
+#ifndef COMMON_LINUX_HTTP_UPLOAD_H__
+#define COMMON_LINUX_HTTP_UPLOAD_H__
+
+#include <map>
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+
+using std::map;
+
+class HTTPUpload {
+ public:
+ // Sends the given sets of parameters and files as a multipart POST
+ // request to the given URL.
+ // Each key in |files| is the name of the file part of the request
+ // (i.e. it corresponds to the name= attribute on an <input type="file">.
+ // Parameter names must contain only printable ASCII characters,
+ // and may not contain a quote (") character.
+ // Only HTTP(S) URLs are currently supported. Returns true on success.
+ // If the request is successful and response_body is non-NULL,
+ // the response body will be returned in response_body.
+ // If response_code is non-NULL, it will be set to the HTTP response code
+ // received (or 0 if the request failed before getting an HTTP response).
+ // If the send fails, a description of the error will be
+ // returned in error_description.
+ static bool SendRequest(const string& url,
+ const map<string, string>& parameters,
+ const map<string, string>& files,
+ const string& proxy,
+ const string& proxy_user_pwd,
+ const string& ca_certificate_file,
+ string* response_body,
+ long* response_code,
+ string* error_description);
+
+ private:
+ // Checks that the given list of parameters has only printable
+ // ASCII characters in the parameter name, and does not contain
+ // any quote (") characters. Returns true if so.
+ static bool CheckParameters(const map<string, string>& parameters);
+
+ // Checks the curl_lib parameter points to a valid curl lib.
+ static bool CheckCurlLib(void* curl_lib);
+
+ // No instances of this class should be created.
+ // Disallow all constructors, destructors, and operator=.
+ HTTPUpload();
+ explicit HTTPUpload(const HTTPUpload&);
+ void operator=(const HTTPUpload&);
+ ~HTTPUpload();
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_HTTP_UPLOAD_H__
diff --git a/contrib/libs/breakpad/src/common/linux/ignore_ret.h b/contrib/libs/breakpad/src/common/linux/ignore_ret.h
new file mode 100644
index 0000000000..efd274c20c
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/ignore_ret.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_IGNORE_RET_H_
+#define COMMON_LINUX_IGNORE_RET_H_
+
+// Some compilers are prone to warn about unused return values. In cases where
+// either a) the call cannot fail, or b) there is nothing that can be done when
+// the call fails, IGNORE_RET() can be used to mark the return code as ignored.
+// This avoids spurious compiler warnings.
+
+#define IGNORE_RET(x) do { if (x) {} } while (0)
+
+#endif // COMMON_LINUX_IGNORE_RET_H_
diff --git a/contrib/libs/breakpad/src/common/linux/libcurl_wrapper.cc b/contrib/libs/breakpad/src/common/linux/libcurl_wrapper.cc
new file mode 100644
index 0000000000..fdb200f8e3
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/libcurl_wrapper.cc
@@ -0,0 +1,338 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <dlfcn.h>
+
+#include <iostream>
+#include <string>
+
+#include "common/linux/libcurl_wrapper.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+LibcurlWrapper::LibcurlWrapper()
+ : init_ok_(false),
+ curl_lib_(nullptr),
+ last_curl_error_(""),
+ curl_(nullptr),
+ formpost_(nullptr),
+ lastptr_(nullptr),
+ headerlist_(nullptr) {}
+
+LibcurlWrapper::~LibcurlWrapper() {
+ if (init_ok_) {
+ (*easy_cleanup_)(curl_);
+ dlclose(curl_lib_);
+ }
+}
+
+bool LibcurlWrapper::SetProxy(const string& proxy_host,
+ const string& proxy_userpwd) {
+ if (!CheckInit()) return false;
+
+ // Set proxy information if necessary.
+ if (!proxy_host.empty()) {
+ (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str());
+ } else {
+ std::cout << "SetProxy called with empty proxy host.";
+ return false;
+ }
+ if (!proxy_userpwd.empty()) {
+ (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str());
+ } else {
+ std::cout << "SetProxy called with empty proxy username/password.";
+ return false;
+ }
+ std::cout << "Set proxy host to " << proxy_host;
+ return true;
+}
+
+bool LibcurlWrapper::AddFile(const string& upload_file_path,
+ const string& basename) {
+ if (!CheckInit()) return false;
+
+ std::cout << "Adding " << upload_file_path << " to form upload.";
+ // Add form file.
+ (*formadd_)(&formpost_, &lastptr_,
+ CURLFORM_COPYNAME, basename.c_str(),
+ CURLFORM_FILE, upload_file_path.c_str(),
+ CURLFORM_END);
+
+ return true;
+}
+
+// Callback to get the response data from server.
+static size_t WriteCallback(void* ptr, size_t size,
+ size_t nmemb, void* userp) {
+ if (!userp)
+ return 0;
+
+ string* response = reinterpret_cast<string*>(userp);
+ size_t real_size = size * nmemb;
+ response->append(reinterpret_cast<char*>(ptr), real_size);
+ return real_size;
+}
+
+bool LibcurlWrapper::SendRequest(const string& url,
+ const std::map<string, string>& parameters,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ std::map<string, string>::const_iterator iter = parameters.begin();
+ for (; iter != parameters.end(); ++iter)
+ (*formadd_)(&formpost_, &lastptr_,
+ CURLFORM_COPYNAME, iter->first.c_str(),
+ CURLFORM_COPYCONTENTS, iter->second.c_str(),
+ CURLFORM_END);
+
+ (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_);
+
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::SendGetRequest(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ (*easy_setopt_)(curl_, CURLOPT_HTTPGET, 1L);
+
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::SendPutRequest(const string& url,
+ const string& path,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ FILE* file = fopen(path.c_str(), "rb");
+ (*easy_setopt_)(curl_, CURLOPT_UPLOAD, 1L);
+ (*easy_setopt_)(curl_, CURLOPT_PUT, 1L);
+ (*easy_setopt_)(curl_, CURLOPT_READDATA, file);
+
+ bool success = SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+
+ fclose(file);
+ return success;
+}
+
+bool LibcurlWrapper::SendSimplePostRequest(const string& url,
+ const string& body,
+ const string& content_type,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ if (!CheckInit()) return false;
+
+ (*easy_setopt_)(curl_, CURLOPT_POSTFIELDSIZE, body.size());
+ (*easy_setopt_)(curl_, CURLOPT_COPYPOSTFIELDS, body.c_str());
+
+ if (!content_type.empty()) {
+ string content_type_header = "Content-Type: " + content_type;
+ headerlist_ = (*slist_append_)(
+ headerlist_,
+ content_type_header.c_str());
+ }
+
+ return SendRequestInner(url, http_status_code, http_header_data,
+ http_response_data);
+}
+
+bool LibcurlWrapper::Init() {
+ // First check to see if libcurl was statically linked:
+ curl_lib_ = dlopen(nullptr, RTLD_NOW);
+ if (curl_lib_ &&
+ (!dlsym(curl_lib_, "curl_easy_init") ||
+ !dlsym(curl_lib_, "curl_easy_setopt"))) {
+ // Not statically linked, try again below.
+ dlerror(); // Clear dlerror before attempting to open libraries.
+ dlclose(curl_lib_);
+ curl_lib_ = nullptr;
+ }
+ if (!curl_lib_) {
+ curl_lib_ = dlopen("libcurl.so", RTLD_NOW);
+ }
+ if (!curl_lib_) {
+ curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW);
+ }
+ if (!curl_lib_) {
+ curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW);
+ }
+ if (!curl_lib_) {
+ std::cout << "Could not find libcurl via dlopen";
+ return false;
+ }
+
+ if (!SetFunctionPointers()) {
+ std::cout << "Could not find function pointers";
+ return false;
+ }
+
+ curl_ = (*easy_init_)();
+
+ last_curl_error_ = "No Error";
+
+ if (!curl_) {
+ dlclose(curl_lib_);
+ std::cout << "Curl initialization failed";
+ return false;
+ }
+
+ init_ok_ = true;
+ return true;
+}
+
+#define SET_AND_CHECK_FUNCTION_POINTER(var, function_name, type) \
+ var = reinterpret_cast<type>(dlsym(curl_lib_, function_name)); \
+ if (!var) { \
+ std::cout << "Could not find libcurl function " << function_name; \
+ init_ok_ = false; \
+ return false; \
+ }
+
+bool LibcurlWrapper::SetFunctionPointers() {
+
+ SET_AND_CHECK_FUNCTION_POINTER(easy_init_,
+ "curl_easy_init",
+ CURL*(*)());
+
+ SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_,
+ "curl_easy_setopt",
+ CURLcode(*)(CURL*, CURLoption, ...));
+
+ SET_AND_CHECK_FUNCTION_POINTER(formadd_, "curl_formadd",
+ CURLFORMcode(*)(curl_httppost**, curl_httppost**, ...));
+
+ SET_AND_CHECK_FUNCTION_POINTER(slist_append_, "curl_slist_append",
+ curl_slist*(*)(curl_slist*, const char*));
+
+ SET_AND_CHECK_FUNCTION_POINTER(easy_perform_,
+ "curl_easy_perform",
+ CURLcode(*)(CURL*));
+
+ SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_,
+ "curl_easy_cleanup",
+ void(*)(CURL*));
+
+ SET_AND_CHECK_FUNCTION_POINTER(easy_getinfo_,
+ "curl_easy_getinfo",
+ CURLcode(*)(CURL*, CURLINFO info, ...));
+
+ SET_AND_CHECK_FUNCTION_POINTER(easy_reset_,
+ "curl_easy_reset",
+ void(*)(CURL*));
+
+ SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_,
+ "curl_slist_free_all",
+ void(*)(curl_slist*));
+
+ SET_AND_CHECK_FUNCTION_POINTER(formfree_,
+ "curl_formfree",
+ void(*)(curl_httppost*));
+ return true;
+}
+
+bool LibcurlWrapper::SendRequestInner(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data) {
+ string url_copy(url);
+ (*easy_setopt_)(curl_, CURLOPT_URL, url_copy.c_str());
+
+ // Disable 100-continue header.
+ char buf[] = "Expect:";
+ headerlist_ = (*slist_append_)(headerlist_, buf);
+ (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
+
+ if (http_response_data != nullptr) {
+ http_response_data->clear();
+ (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback);
+ (*easy_setopt_)(curl_, CURLOPT_WRITEDATA,
+ reinterpret_cast<void*>(http_response_data));
+ }
+ if (http_header_data != nullptr) {
+ http_header_data->clear();
+ (*easy_setopt_)(curl_, CURLOPT_HEADERFUNCTION, WriteCallback);
+ (*easy_setopt_)(curl_, CURLOPT_HEADERDATA,
+ reinterpret_cast<void*>(http_header_data));
+ }
+ CURLcode err_code = CURLE_OK;
+ err_code = (*easy_perform_)(curl_);
+ easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)>
+ (dlsym(curl_lib_, "curl_easy_strerror"));
+
+ if (http_status_code != nullptr) {
+ (*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code);
+ }
+
+#ifndef NDEBUG
+ if (err_code != CURLE_OK)
+ fprintf(stderr, "Failed to send http request to %s, error: %s\n",
+ url.c_str(),
+ (*easy_strerror_)(err_code));
+#endif
+
+ Reset();
+
+ return err_code == CURLE_OK;
+}
+
+void LibcurlWrapper::Reset() {
+ if (headerlist_ != nullptr) {
+ (*slist_free_all_)(headerlist_);
+ headerlist_ = nullptr;
+ }
+
+ if (formpost_ != nullptr) {
+ (*formfree_)(formpost_);
+ formpost_ = nullptr;
+ }
+
+ (*easy_reset_)(curl_);
+}
+
+bool LibcurlWrapper::CheckInit() {
+ if (!init_ok_) {
+ std::cout << "LibcurlWrapper: You must call Init(), and have it return "
+ "'true' before invoking any other methods.\n";
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/libcurl_wrapper.h b/contrib/libs/breakpad/src/common/linux/libcurl_wrapper.h
new file mode 100644
index 0000000000..823f83c7ee
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/libcurl_wrapper.h
@@ -0,0 +1,119 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A wrapper for libcurl to do HTTP Uploads, to support easy mocking
+// and unit testing of the HTTPUpload class.
+
+#ifndef COMMON_LINUX_LIBCURL_WRAPPER_H_
+#define COMMON_LINUX_LIBCURL_WRAPPER_H_
+
+#include <string>
+#include <map>
+
+#include "common/using_std_string.h"
+#include "third_party/curl/curl.h"
+
+namespace google_breakpad {
+class LibcurlWrapper {
+ public:
+ LibcurlWrapper();
+ virtual ~LibcurlWrapper();
+ virtual bool Init();
+ virtual bool SetProxy(const string& proxy_host,
+ const string& proxy_userpwd);
+ virtual bool AddFile(const string& upload_file_path,
+ const string& basename);
+ virtual bool SendRequest(const string& url,
+ const std::map<string, string>& parameters,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+ bool SendGetRequest(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+ bool SendPutRequest(const string& url,
+ const string& path,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+ bool SendSimplePostRequest(const string& url,
+ const string& body,
+ const string& content_type,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+
+ private:
+ // This function initializes class state corresponding to function
+ // pointers into the CURL library.
+ bool SetFunctionPointers();
+
+ bool SendRequestInner(const string& url,
+ long* http_status_code,
+ string* http_header_data,
+ string* http_response_data);
+
+ void Reset();
+
+ bool CheckInit();
+
+ bool init_ok_; // Whether init succeeded
+ void* curl_lib_; // Pointer to result of dlopen() on
+ // curl library
+ string last_curl_error_; // The text of the last error when
+ // dealing
+ // with CURL.
+
+ CURL* curl_; // Pointer for handle for CURL calls.
+
+ CURL* (*easy_init_)(void);
+
+ // Stateful pointers for calling into curl_formadd()
+ struct curl_httppost* formpost_;
+ struct curl_httppost* lastptr_;
+ struct curl_slist* headerlist_;
+
+ // Function pointers into CURL library
+ CURLcode (*easy_setopt_)(CURL*, CURLoption, ...);
+ CURLFORMcode (*formadd_)(struct curl_httppost**,
+ struct curl_httppost**, ...);
+ struct curl_slist* (*slist_append_)(struct curl_slist*, const char*);
+ void (*slist_free_all_)(struct curl_slist*);
+ CURLcode (*easy_perform_)(CURL*);
+ const char* (*easy_strerror_)(CURLcode);
+ void (*easy_cleanup_)(CURL*);
+ CURLcode (*easy_getinfo_)(CURL*, CURLINFO info, ...);
+ void (*easy_reset_)(CURL*);
+ void (*formfree_)(struct curl_httppost*);
+
+};
+}
+
+#endif // COMMON_LINUX_LIBCURL_WRAPPER_H_
diff --git a/contrib/libs/breakpad/src/common/linux/linux_libc_support.cc b/contrib/libs/breakpad/src/common/linux/linux_libc_support.cc
new file mode 100644
index 0000000000..dd29296262
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/linux_libc_support.cc
@@ -0,0 +1,237 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This source file provides replacements for libc functions that we need. If
+// we call the libc functions directly we risk crashing in the dynamic linker
+// as it tries to resolve uncached PLT entries.
+
+#include "common/linux/linux_libc_support.h"
+
+#include <stddef.h>
+
+extern "C" {
+
+size_t my_strlen(const char* s) {
+ size_t len = 0;
+ while (*s++) len++;
+ return len;
+}
+
+int my_strcmp(const char* a, const char* b) {
+ for (;;) {
+ if (*a < *b)
+ return -1;
+ else if (*a > *b)
+ return 1;
+ else if (*a == 0)
+ return 0;
+ a++;
+ b++;
+ }
+}
+
+int my_strncmp(const char* a, const char* b, size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ if (*a < *b)
+ return -1;
+ else if (*a > *b)
+ return 1;
+ else if (*a == 0)
+ return 0;
+ a++;
+ b++;
+ }
+
+ return 0;
+}
+
+// Parse a non-negative integer.
+// result: (output) the resulting non-negative integer
+// s: a NUL terminated string
+// Return true iff successful.
+bool my_strtoui(int* result, const char* s) {
+ if (*s == 0)
+ return false;
+ int r = 0;
+ for (;; s++) {
+ if (*s == 0)
+ break;
+ const int old_r = r;
+ r *= 10;
+ if (*s < '0' || *s > '9')
+ return false;
+ r += *s - '0';
+ if (r < old_r)
+ return false;
+ }
+
+ *result = r;
+ return true;
+}
+
+// Return the length of the given unsigned integer when expressed in base 10.
+unsigned my_uint_len(uintmax_t i) {
+ if (!i)
+ return 1;
+
+ int len = 0;
+ while (i) {
+ len++;
+ i /= 10;
+ }
+
+ return len;
+}
+
+// Convert an unsigned integer to a string
+// output: (output) the resulting string is written here. This buffer must be
+// large enough to hold the resulting string. Call |my_uint_len| to get the
+// required length.
+// i: the unsigned integer to serialise.
+// i_len: the length of the integer in base 10 (see |my_uint_len|).
+void my_uitos(char* output, uintmax_t i, unsigned i_len) {
+ for (unsigned index = i_len; index; --index, i /= 10)
+ output[index - 1] = '0' + (i % 10);
+}
+
+const char* my_strchr(const char* haystack, char needle) {
+ while (*haystack && *haystack != needle)
+ haystack++;
+ if (*haystack == needle)
+ return haystack;
+ return (const char*) 0;
+}
+
+const char* my_strrchr(const char* haystack, char needle) {
+ const char* ret = NULL;
+ while (*haystack) {
+ if (*haystack == needle)
+ ret = haystack;
+ haystack++;
+ }
+ return ret;
+}
+
+void* my_memchr(const void* src, int needle, size_t src_len) {
+ const unsigned char* p = (const unsigned char*)src;
+ const unsigned char* p_end = p + src_len;
+ for (; p < p_end; ++p) {
+ if (*p == needle)
+ return (void*)p;
+ }
+ return NULL;
+}
+
+// Read a hex value
+// result: (output) the resulting value
+// s: a string
+// Returns a pointer to the first invalid charactor.
+const char* my_read_hex_ptr(uintptr_t* result, const char* s) {
+ uintptr_t r = 0;
+
+ for (;; ++s) {
+ if (*s >= '0' && *s <= '9') {
+ r <<= 4;
+ r += *s - '0';
+ } else if (*s >= 'a' && *s <= 'f') {
+ r <<= 4;
+ r += (*s - 'a') + 10;
+ } else if (*s >= 'A' && *s <= 'F') {
+ r <<= 4;
+ r += (*s - 'A') + 10;
+ } else {
+ break;
+ }
+ }
+
+ *result = r;
+ return s;
+}
+
+const char* my_read_decimal_ptr(uintptr_t* result, const char* s) {
+ uintptr_t r = 0;
+
+ for (;; ++s) {
+ if (*s >= '0' && *s <= '9') {
+ r *= 10;
+ r += *s - '0';
+ } else {
+ break;
+ }
+ }
+ *result = r;
+ return s;
+}
+
+void my_memset(void* ip, char c, size_t len) {
+ char* p = (char*) ip;
+ while (len--)
+ *p++ = c;
+}
+
+size_t my_strlcpy(char* s1, const char* s2, size_t len) {
+ size_t pos1 = 0;
+ size_t pos2 = 0;
+
+ while (s2[pos2] != '\0') {
+ if (pos1 + 1 < len) {
+ s1[pos1] = s2[pos2];
+ pos1++;
+ }
+ pos2++;
+ }
+ if (len > 0)
+ s1[pos1] = '\0';
+
+ return pos2;
+}
+
+size_t my_strlcat(char* s1, const char* s2, size_t len) {
+ size_t pos1 = 0;
+
+ while (pos1 < len && s1[pos1] != '\0')
+ pos1++;
+
+ if (pos1 == len)
+ return pos1;
+
+ return pos1 + my_strlcpy(s1 + pos1, s2, len - pos1);
+}
+
+int my_isspace(int ch) {
+ // Matches the C locale.
+ const char spaces[] = " \t\f\n\r\t\v";
+ for (size_t i = 0; i < sizeof(spaces); i++) {
+ if (ch == spaces[i])
+ return 1;
+ }
+ return 0;
+}
+
+} // extern "C"
diff --git a/contrib/libs/breakpad/src/common/linux/linux_libc_support.h b/contrib/libs/breakpad/src/common/linux/linux_libc_support.h
new file mode 100644
index 0000000000..ec5a8d6b6b
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/linux_libc_support.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header provides replacements for libc functions that we need. We if
+// call the libc functions directly we risk crashing in the dynamic linker as
+// it tries to resolve uncached PLT entries.
+
+#ifndef CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
+#define CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/types.h>
+
+extern "C" {
+
+extern size_t my_strlen(const char* s);
+
+extern int my_strcmp(const char* a, const char* b);
+
+extern int my_strncmp(const char* a, const char* b, size_t len);
+
+// Parse a non-negative integer.
+// result: (output) the resulting non-negative integer
+// s: a NUL terminated string
+// Return true iff successful.
+extern bool my_strtoui(int* result, const char* s);
+
+// Return the length of the given unsigned integer when expressed in base 10.
+extern unsigned my_uint_len(uintmax_t i);
+
+// Convert an unsigned integer to a string
+// output: (output) the resulting string is written here. This buffer must be
+// large enough to hold the resulting string. Call |my_uint_len| to get the
+// required length.
+// i: the unsigned integer to serialise.
+// i_len: the length of the integer in base 10 (see |my_uint_len|).
+extern void my_uitos(char* output, uintmax_t i, unsigned i_len);
+
+extern const char* my_strchr(const char* haystack, char needle);
+
+extern const char* my_strrchr(const char* haystack, char needle);
+
+// Read a hex value
+// result: (output) the resulting value
+// s: a string
+// Returns a pointer to the first invalid charactor.
+extern const char* my_read_hex_ptr(uintptr_t* result, const char* s);
+
+extern const char* my_read_decimal_ptr(uintptr_t* result, const char* s);
+
+extern void my_memset(void* ip, char c, size_t len);
+
+extern void* my_memchr(const void* src, int c, size_t len);
+
+// The following are considered safe to use in a compromised environment.
+// Besides, this gives the compiler an opportunity to optimize their calls.
+#define my_memcpy memcpy
+#define my_memmove memmove
+#define my_memcmp memcmp
+
+extern size_t my_strlcpy(char* s1, const char* s2, size_t len);
+
+extern size_t my_strlcat(char* s1, const char* s2, size_t len);
+
+extern int my_isspace(int ch);
+
+} // extern "C"
+
+#endif // CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
diff --git a/contrib/libs/breakpad/src/common/linux/memory_mapped_file.cc b/contrib/libs/breakpad/src/common/linux/memory_mapped_file.cc
new file mode 100644
index 0000000000..99362945ca
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/memory_mapped_file.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// memory_mapped_file.cc: Implement google_breakpad::MemoryMappedFile.
+// See memory_mapped_file.h for details.
+
+#include "common/linux/memory_mapped_file.h"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#if defined(__ANDROID__)
+#include <sys/stat.h>
+#endif
+#include <unistd.h>
+
+#include "common/memory_range.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+MemoryMappedFile::MemoryMappedFile() {}
+
+MemoryMappedFile::MemoryMappedFile(const char* path, size_t offset) {
+ Map(path, offset);
+}
+
+MemoryMappedFile::~MemoryMappedFile() {
+ Unmap();
+}
+
+#include <unistd.h>
+
+bool MemoryMappedFile::Map(const char* path, size_t offset) {
+ Unmap();
+
+ int fd = sys_open(path, O_RDONLY, 0);
+ if (fd == -1) {
+ return false;
+ }
+
+#if defined(__x86_64__) || defined(__aarch64__) || \
+ (defined(__mips__) && _MIPS_SIM == _ABI64)
+
+ struct kernel_stat st;
+ if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
+#else
+ struct kernel_stat64 st;
+ if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) {
+#endif
+ sys_close(fd);
+ return false;
+ }
+
+ // Strangely file size can be negative, but we check above that it is not.
+ size_t file_len = static_cast<size_t>(st.st_size);
+ // If the file does not extend beyond the offset, simply use an empty
+ // MemoryRange and return true. Don't bother to call mmap()
+ // even though mmap() can handle an empty file on some platforms.
+ if (offset >= file_len) {
+ sys_close(fd);
+ return true;
+ }
+
+ size_t content_len = file_len - offset;
+ void* data = sys_mmap(NULL, content_len, PROT_READ, MAP_PRIVATE, fd, offset);
+ sys_close(fd);
+ if (data == MAP_FAILED) {
+ return false;
+ }
+
+ content_.Set(data, content_len);
+ return true;
+}
+
+void MemoryMappedFile::Unmap() {
+ if (content_.data()) {
+ sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length());
+ content_.Set(NULL, 0);
+ }
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/memory_mapped_file.h b/contrib/libs/breakpad/src/common/linux/memory_mapped_file.h
new file mode 100644
index 0000000000..fa660cc91a
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/memory_mapped_file.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// memory_mapped_file.h: Define the google_breakpad::MemoryMappedFile
+// class, which maps a file into memory for read-only access.
+
+#ifndef COMMON_LINUX_MEMORY_MAPPED_FILE_H_
+#define COMMON_LINUX_MEMORY_MAPPED_FILE_H_
+
+#include <stddef.h>
+#include "common/basictypes.h"
+#include "common/memory_range.h"
+
+namespace google_breakpad {
+
+// A utility class for mapping a file into memory for read-only access of
+// the file content. Its implementation avoids calling into libc functions
+// by directly making system calls for open, close, mmap, and munmap.
+class MemoryMappedFile {
+ public:
+ MemoryMappedFile();
+
+ // Constructor that calls Map() to map a file at |path| into memory.
+ // If Map() fails, the object behaves as if it is default constructed.
+ MemoryMappedFile(const char* path, size_t offset);
+
+ ~MemoryMappedFile();
+
+ // Maps a file at |path| into memory, which can then be accessed via
+ // content() as a MemoryRange object or via data(), and returns true on
+ // success. Mapping an empty file will succeed but with data() and size()
+ // returning NULL and 0, respectively. An existing mapping is unmapped
+ // before a new mapping is created.
+ bool Map(const char* path, size_t offset);
+
+ // Unmaps the memory for the mapped file. It's a no-op if no file is
+ // mapped.
+ void Unmap();
+
+ // Returns a MemoryRange object that covers the memory for the mapped
+ // file. The MemoryRange object is empty if no file is mapped.
+ const MemoryRange& content() const { return content_; }
+
+ // Returns a pointer to the beginning of the memory for the mapped file.
+ // or NULL if no file is mapped or the mapped file is empty.
+ const void* data() const { return content_.data(); }
+
+ // Returns the size in bytes of the mapped file, or zero if no file
+ // is mapped.
+ size_t size() const { return content_.length(); }
+
+ private:
+ // Mapped file content as a MemoryRange object.
+ MemoryRange content_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_MEMORY_MAPPED_FILE_H_
diff --git a/contrib/libs/breakpad/src/common/linux/safe_readlink.cc b/contrib/libs/breakpad/src/common/linux/safe_readlink.cc
new file mode 100644
index 0000000000..870c28af3b
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/safe_readlink.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// safe_readlink.cc: Implement google_breakpad::SafeReadLink.
+// See safe_readlink.h for details.
+
+#include <stddef.h>
+
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+bool SafeReadLink(const char* path, char* buffer, size_t buffer_size) {
+ // sys_readlink() does not add a NULL byte to |buffer|. In order to return
+ // a NULL-terminated string in |buffer|, |buffer_size| should be at least
+ // one byte longer than the expected path length. Also, sys_readlink()
+ // returns the actual path length on success, which does not count the
+ // NULL byte, so |result_size| should be less than |buffer_size|.
+ ssize_t result_size = sys_readlink(path, buffer, buffer_size);
+ if (result_size >= 0 && static_cast<size_t>(result_size) < buffer_size) {
+ buffer[result_size] = '\0';
+ return true;
+ }
+ return false;
+}
+
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/safe_readlink.h b/contrib/libs/breakpad/src/common/linux/safe_readlink.h
new file mode 100644
index 0000000000..4ae131b580
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/safe_readlink.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// safe_readlink.h: Define the google_breakpad::SafeReadLink function,
+// which wraps sys_readlink and gurantees the result is NULL-terminated.
+
+#ifndef COMMON_LINUX_SAFE_READLINK_H_
+#define COMMON_LINUX_SAFE_READLINK_H_
+
+#include <stddef.h>
+
+namespace google_breakpad {
+
+// This function wraps sys_readlink() and performs the same functionalty,
+// but guarantees |buffer| is NULL-terminated if sys_readlink() returns
+// no error. It takes the same arguments as sys_readlink(), but unlike
+// sys_readlink(), it returns true on success.
+//
+// |buffer_size| specifies the size of |buffer| in bytes. As this function
+// always NULL-terminates |buffer| on success, |buffer_size| should be
+// at least one byte longer than the expected path length (e.g. PATH_MAX,
+// which is typically defined as the maximum length of a path name
+// including the NULL byte).
+//
+// The implementation of this function calls sys_readlink() instead of
+// readlink(), it can thus be used in the context where calling to libc
+// functions is discouraged.
+bool SafeReadLink(const char* path, char* buffer, size_t buffer_size);
+
+// Same as the three-argument version of SafeReadLink() but deduces the
+// size of |buffer| if it is a char array of known size.
+template <size_t N>
+bool SafeReadLink(const char* path, char (&buffer)[N]) {
+ return SafeReadLink(path, buffer, sizeof(buffer));
+}
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_SAFE_READLINK_H_
diff --git a/contrib/libs/breakpad/src/common/linux/symbol_collector_client.cc b/contrib/libs/breakpad/src/common/linux/symbol_collector_client.cc
new file mode 100644
index 0000000000..92b25ddba9
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/symbol_collector_client.cc
@@ -0,0 +1,195 @@
+// Copyright (c) 2019 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "common/linux/symbol_collector_client.h"
+
+#include <stdio.h>
+
+#include <iostream>
+#include <regex>
+
+#include "common/linux/libcurl_wrapper.h"
+
+namespace google_breakpad {
+namespace sym_upload {
+
+// static
+bool SymbolCollectorClient::CreateUploadUrl(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ UploadUrlResponse* uploadUrlResponse) {
+ string header, response;
+ long response_code;
+
+ string url = api_url + "/v1/uploads:create";
+ if (!api_key.empty()) {
+ url += "?key=" + api_key;
+ }
+
+ if (!libcurl_wrapper->SendSimplePostRequest(url,
+ /*body=*/"",
+ /*content_type=*/"",
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to create upload url.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+
+ // Note camel-case rather than underscores.
+ std::regex upload_url_regex("\"uploadUrl\": \"([^\"]+)\"");
+ std::regex upload_key_regex("\"uploadKey\": \"([^\"]+)\"");
+
+ std::smatch upload_url_match;
+ if (!std::regex_search(response, upload_url_match, upload_url_regex) ||
+ upload_url_match.size() != 2) {
+ printf("Failed to parse create url response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+ string upload_url = upload_url_match[1].str();
+
+ std::smatch upload_key_match;
+ if (!std::regex_search(response, upload_key_match, upload_key_regex) ||
+ upload_key_match.size() != 2) {
+ printf("Failed to parse create url response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+ string upload_key = upload_key_match[1].str();
+
+ uploadUrlResponse->upload_url = upload_url;
+ uploadUrlResponse->upload_key = upload_key;
+ return true;
+}
+
+// static
+CompleteUploadResult SymbolCollectorClient::CompleteUpload(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& upload_key,
+ const string& debug_file,
+ const string& debug_id,
+ const string& type) {
+ string header, response;
+ long response_code;
+
+ string url = api_url + "/v1/uploads/" + upload_key + ":complete";
+ if (!api_key.empty()) {
+ url += "?key=" + api_key;
+ }
+ string body =
+ "{ symbol_id: {"
+ "debug_file: \"" + debug_file + "\", "
+ "debug_id: \"" + debug_id + "\" }, "
+ "symbol_upload_type: \"" + type + "\" }";
+
+ if (!libcurl_wrapper->SendSimplePostRequest(url,
+ body,
+ "application/son",
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to complete upload.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return CompleteUploadResult::Error;
+ }
+
+ std::regex result_regex("\"result\": \"([^\"]+)\"");
+ std::smatch result_match;
+ if (!std::regex_search(response, result_match, result_regex) ||
+ result_match.size() != 2) {
+ printf("Failed to parse complete upload response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return CompleteUploadResult::Error;
+ }
+ string result = result_match[1].str();
+
+ if (result.compare("DUPLICATE_DATA") == 0) {
+ return CompleteUploadResult::DuplicateData;
+ }
+
+ return CompleteUploadResult::Ok;
+}
+
+// static
+SymbolStatus SymbolCollectorClient::CheckSymbolStatus(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& debug_file,
+ const string& debug_id) {
+ string header, response;
+ long response_code;
+ string url = api_url +
+ "/v1/symbols/" + debug_file + "/" + debug_id + ":checkStatus";
+ if (!api_key.empty()) {
+ url += "?key=" + api_key;
+ }
+
+ if (!libcurl_wrapper->SendGetRequest(
+ url,
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to check symbol status, error message.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return SymbolStatus::Unknown;
+ }
+
+ std::regex status_regex("\"status\": \"([^\"]+)\"");
+ std::smatch status_match;
+ if (!std::regex_search(response, status_match, status_regex) ||
+ status_match.size() != 2) {
+ printf("Failed to parse check symbol status response.");
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return SymbolStatus::Unknown;
+ }
+ string status = status_match[1].str();
+
+ return (status.compare("FOUND") == 0) ?
+ SymbolStatus::Found :
+ SymbolStatus::Missing;
+}
+
+} // namespace sym_upload
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/symbol_collector_client.h b/contrib/libs/breakpad/src/common/linux/symbol_collector_client.h
new file mode 100644
index 0000000000..0e23242a2b
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/symbol_collector_client.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2019, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_SYMBOL_COLLECTOR_CLIENT_H_
+#define COMMON_LINUX_SYMBOL_COLLECTOR_CLIENT_H_
+
+#include <string>
+
+#include "common/linux/libcurl_wrapper.h"
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+namespace sym_upload {
+
+struct UploadUrlResponse {
+ string upload_url;
+ string upload_key;
+};
+
+enum SymbolStatus {
+ Found,
+ Missing,
+ Unknown
+};
+
+enum CompleteUploadResult {
+ Ok,
+ DuplicateData,
+ Error
+};
+
+// Helper class to communicate with a sym-upload-v2 service over HTTP/REST,
+// via libcurl.
+class SymbolCollectorClient {
+ public:
+ static bool CreateUploadUrl(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ UploadUrlResponse* uploadUrlResponse);
+
+ static CompleteUploadResult CompleteUpload(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& upload_key,
+ const string& debug_file,
+ const string& debug_id,
+ const string& type);
+
+ static SymbolStatus CheckSymbolStatus(
+ LibcurlWrapper* libcurl_wrapper,
+ const string& api_url,
+ const string& api_key,
+ const string& debug_file,
+ const string& debug_id);
+};
+
+} // namespace sym_upload
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_SYMBOL_COLLECTOR_CLIENT_H_
diff --git a/contrib/libs/breakpad/src/common/linux/symbol_upload.cc b/contrib/libs/breakpad/src/common/linux/symbol_upload.cc
new file mode 100644
index 0000000000..1d5ff71965
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/symbol_upload.cc
@@ -0,0 +1,284 @@
+// Copyright (c) 2011 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper
+// function for linux symbol upload tool.
+
+#include "common/linux/symbol_upload.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <functional>
+#include <iostream>
+#include <vector>
+
+#include "common/linux/http_upload.h"
+#include "common/linux/libcurl_wrapper.h"
+#include "common/linux/symbol_collector_client.h"
+
+namespace google_breakpad {
+namespace sym_upload {
+
+void TokenizeByChar(const string& source_string, int c,
+ std::vector<string>* results) {
+ assert(results);
+ string::size_type cur_pos = 0, next_pos = 0;
+ while ((next_pos = source_string.find(c, cur_pos)) != string::npos) {
+ if (next_pos != cur_pos)
+ results->push_back(source_string.substr(cur_pos, next_pos - cur_pos));
+ cur_pos = next_pos + 1;
+ }
+ if (cur_pos < source_string.size() && next_pos != cur_pos)
+ results->push_back(source_string.substr(cur_pos));
+}
+
+//=============================================================================
+// Parse out the module line which have 5 parts.
+// MODULE <os> <cpu> <uuid> <module-name>
+bool ModuleDataForSymbolFile(const string& file,
+ std::vector<string>* module_parts) {
+ assert(module_parts);
+ const size_t kModulePartNumber = 5;
+ FILE* fp = fopen(file.c_str(), "r");
+ if (fp) {
+ char buffer[1024];
+ if (fgets(buffer, sizeof(buffer), fp)) {
+ string line(buffer);
+ string::size_type line_break_pos = line.find_first_of('\n');
+ if (line_break_pos == string::npos) {
+ assert(0 && "The file is invalid!");
+ fclose(fp);
+ return false;
+ }
+ line.resize(line_break_pos);
+ const char kDelimiter = ' ';
+ TokenizeByChar(line, kDelimiter, module_parts);
+ if (module_parts->size() != kModulePartNumber)
+ module_parts->clear();
+ }
+ fclose(fp);
+ }
+
+ return module_parts->size() == kModulePartNumber;
+}
+
+//=============================================================================
+string CompactIdentifier(const string& uuid) {
+ std::vector<string> components;
+ TokenizeByChar(uuid, '-', &components);
+ string result;
+ for (size_t i = 0; i < components.size(); ++i)
+ result += components[i];
+ return result;
+}
+
+// |options| describes the current sym_upload options.
+// |module_parts| contains the strings parsed from the MODULE entry of the
+// Breakpad symbol file being uploaded.
+// |compacted_id| is the debug_id from the MODULE entry of the Breakpad symbol
+// file being uploaded, with all hyphens removed.
+bool SymUploadV1Start(
+ const Options& options,
+ std::vector<string> module_parts,
+ const string& compacted_id) {
+ std::map<string, string> parameters;
+ // Add parameters
+ if (!options.version.empty())
+ parameters["version"] = options.version;
+
+ // MODULE <os> <cpu> <uuid> <module-name>
+ // 0 1 2 3 4
+ parameters["os"] = module_parts[1];
+ parameters["cpu"] = module_parts[2];
+ parameters["debug_file"] = module_parts[4];
+ parameters["code_file"] = module_parts[4];
+ parameters["debug_identifier"] = compacted_id;
+
+ std::map<string, string> files;
+ files["symbol_file"] = options.symbolsPath;
+
+ string response, error;
+ long response_code;
+ bool success = HTTPUpload::SendRequest(options.uploadURLStr,
+ parameters,
+ files,
+ options.proxy,
+ options.proxy_user_pwd,
+ /*ca_certificate_file=*/"",
+ &response,
+ &response_code,
+ &error);
+
+ if (!success) {
+ printf("Failed to send symbol file: %s\n", error.c_str());
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ } else if (response_code == 0) {
+ printf("Failed to send symbol file: No response code\n");
+ } else if (response_code != 200) {
+ printf("Failed to send symbol file: Response code %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ } else {
+ printf("Successfully sent the symbol file.\n");
+ }
+
+ return success;
+}
+
+// |options| describes the current sym_upload options.
+// |code_id| is the basename of the module for which symbols are being
+// uploaded.
+// |debug_id| is the debug_id of the module for which symbols are being
+// uploaded.
+bool SymUploadV2Start(
+ const Options& options,
+ const string& code_file,
+ const string& debug_id,
+ const string& type) {
+ google_breakpad::LibcurlWrapper libcurl_wrapper;
+ if (!libcurl_wrapper.Init()) {
+ printf("Failed to init google_breakpad::LibcurlWrapper.\n");
+ return false;
+ }
+
+ if (!options.force) {
+ SymbolStatus symbolStatus = SymbolCollectorClient::CheckSymbolStatus(
+ &libcurl_wrapper,
+ options.uploadURLStr,
+ options.api_key,
+ code_file,
+ debug_id);
+ if (symbolStatus == SymbolStatus::Found) {
+ printf("Symbol file already exists, upload aborted."
+ " Use \"-f\" to overwrite.\n");
+ return true;
+ } else if (symbolStatus == SymbolStatus::Unknown) {
+ printf("Failed to check for existing symbol.\n");
+ return false;
+ }
+ }
+
+ UploadUrlResponse uploadUrlResponse;
+ if (!SymbolCollectorClient::CreateUploadUrl(
+ &libcurl_wrapper,
+ options.uploadURLStr,
+ options.api_key,
+ &uploadUrlResponse)) {
+ printf("Failed to create upload URL.\n");
+ return false;
+ }
+
+ string signed_url = uploadUrlResponse.upload_url;
+ string upload_key = uploadUrlResponse.upload_key;
+ string header;
+ string response;
+ long response_code;
+
+ if (!libcurl_wrapper.SendPutRequest(signed_url,
+ options.symbolsPath,
+ &response_code,
+ &header,
+ &response)) {
+ printf("Failed to send symbol file.\n");
+ printf("Response code: %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ } else if (response_code == 0) {
+ printf("Failed to send symbol file: No response code\n");
+ return false;
+ } else if (response_code != 200) {
+ printf("Failed to send symbol file: Response code %ld\n", response_code);
+ printf("Response:\n");
+ printf("%s\n", response.c_str());
+ return false;
+ }
+
+ CompleteUploadResult completeUploadResult =
+ SymbolCollectorClient::CompleteUpload(&libcurl_wrapper,
+ options.uploadURLStr,
+ options.api_key,
+ upload_key,
+ code_file,
+ debug_id,
+ type);
+ if (completeUploadResult == CompleteUploadResult::Error) {
+ printf("Failed to complete upload.\n");
+ return false;
+ } else if (completeUploadResult == CompleteUploadResult::DuplicateData) {
+ printf("Uploaded file checksum matched existing file checksum,"
+ " no change necessary.\n");
+ } else {
+ printf("Successfully sent the symbol file.\n");
+ }
+
+ return true;
+}
+
+//=============================================================================
+void Start(Options* options) {
+ if (options->upload_protocol == UploadProtocol::SYM_UPLOAD_V2) {
+ string code_file;
+ string debug_id;
+ string type;
+
+ if (options->type.empty() || options->type == kBreakpadSymbolType) {
+ // Breakpad upload so read these from input file.
+ std::vector<string> module_parts;
+ if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
+ fprintf(stderr, "Failed to parse symbol file!\n");
+ return;
+ }
+ code_file = module_parts[4];
+ debug_id = CompactIdentifier(module_parts[3]);
+ type = kBreakpadSymbolType;
+ } else {
+ // Native upload so these must be explicitly set.
+ code_file = options->code_file;
+ debug_id = options->debug_id;
+ type = options->type;
+ }
+
+ options->success = SymUploadV2Start(*options, code_file, debug_id, type);
+ } else {
+ std::vector<string> module_parts;
+ if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
+ fprintf(stderr, "Failed to parse symbol file!\n");
+ return;
+ }
+ const string compacted_id = CompactIdentifier(module_parts[3]);
+ options->success = SymUploadV1Start(*options, module_parts, compacted_id);
+ }
+}
+
+} // namespace sym_upload
+} // namespace google_breakpad
diff --git a/contrib/libs/breakpad/src/common/linux/symbol_upload.h b/contrib/libs/breakpad/src/common/linux/symbol_upload.h
new file mode 100644
index 0000000000..9033152bf2
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/symbol_upload.h
@@ -0,0 +1,76 @@
+// -*- mode: c++ -*-
+
+// Copyright (c) 2011 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// symbol_upload.h: helper functions for linux symbol upload tool.
+
+#ifndef COMMON_LINUX_SYMBOL_UPLOAD_H_
+#define COMMON_LINUX_SYMBOL_UPLOAD_H_
+
+#include <string>
+
+#include "common/using_std_string.h"
+
+namespace google_breakpad {
+namespace sym_upload {
+
+enum class UploadProtocol {
+ SYM_UPLOAD_V1,
+ SYM_UPLOAD_V2,
+};
+
+constexpr char kBreakpadSymbolType[] = "BREAKPAD";
+
+struct Options {
+ Options() : upload_protocol(UploadProtocol::SYM_UPLOAD_V1), force(false) {}
+
+ string symbolsPath;
+ string uploadURLStr;
+ string proxy;
+ string proxy_user_pwd;
+ string version;
+ bool success;
+ UploadProtocol upload_protocol;
+ bool force;
+ string api_key;
+
+ // These only need to be set for native symbol uploads.
+ string code_file;
+ string debug_id;
+ string type;
+};
+
+// Starts upload to symbol server with options.
+void Start(Options* options);
+
+} // namespace sym_upload
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_SYMBOL_UPLOAD_H_
diff --git a/contrib/libs/breakpad/src/common/linux/ucontext_constants.h b/contrib/libs/breakpad/src/common/linux/ucontext_constants.h
new file mode 100644
index 0000000000..c390508a1a
--- /dev/null
+++ b/contrib/libs/breakpad/src/common/linux/ucontext_constants.h
@@ -0,0 +1,153 @@
+// Copyright (c) 2012, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header can be included either from a C, C++ or Assembly file.
+// Its purpose is to contain constants that must match the offsets of
+// various fields in ucontext_t.
+//
+// They should match the definitions from signal.h.
+//
+// Used by src/common/linux/breakpad_getcontext.S
+// Tested by src/common/linux/breakpad_getcontext_unittest.cc
+//
+// This header should not be used by anything else.
+
+#ifndef GOOGLEBREAKPAD_COMMON_LINUX_UCONTEXT_CONSTANTS_H
+#define GOOGLEBREAKPAD_COMMON_LINUX_UCONTEXT_CONSTANTS_H
+
+#if defined(__arm__)
+
+#define MCONTEXT_GREGS_OFFSET 32
+#define UCONTEXT_SIGMASK_OFFSET 104
+
+#elif defined(__aarch64__)
+
+#define UCONTEXT_SIGMASK_OFFSET 40
+
+#define MCONTEXT_GREGS_OFFSET 184
+#define MCONTEXT_SP_OFFSET 432
+#define MCONTEXT_PC_OFFSET 440
+#define MCONTEXT_PSTATE_OFFSET 448
+#define MCONTEXT_EXTENSION_OFFSET 464
+
+#define FPSIMD_MAGIC 0x46508001
+
+#define FPSIMD_CONTEXT_MAGIC_OFFSET 0
+#define FPSIMD_CONTEXT_SIZE_OFFSET 4
+#define FPSIMD_CONTEXT_FPSR_OFFSET 8
+#define FPSIMD_CONTEXT_FPCR_OFFSET 12
+#define FPSIMD_CONTEXT_VREGS_OFFSET 16
+#define FPSIMD_CONTEXT_SIZE 528
+
+#define REGISTER_SIZE 8
+#define SIMD_REGISTER_SIZE 16
+
+#elif defined(__i386__)
+
+#define MCONTEXT_GREGS_OFFSET 20
+#define MCONTEXT_GS_OFFSET (MCONTEXT_GREGS_OFFSET + 0*4)
+#define MCONTEXT_FS_OFFSET (MCONTEXT_GREGS_OFFSET + 1*4)
+#define MCONTEXT_ES_OFFSET (MCONTEXT_GREGS_OFFSET + 2*4)
+#define MCONTEXT_DS_OFFSET (MCONTEXT_GREGS_OFFSET + 3*4)
+#define MCONTEXT_EDI_OFFSET (MCONTEXT_GREGS_OFFSET + 4*4)
+#define MCONTEXT_ESI_OFFSET (MCONTEXT_GREGS_OFFSET + 5*4)
+#define MCONTEXT_EBP_OFFSET (MCONTEXT_GREGS_OFFSET + 6*4)
+#define MCONTEXT_ESP_OFFSET (MCONTEXT_GREGS_OFFSET + 7*4)
+#define MCONTEXT_EBX_OFFSET (MCONTEXT_GREGS_OFFSET + 8*4)
+#define MCONTEXT_EDX_OFFSET (MCONTEXT_GREGS_OFFSET + 9*4)
+#define MCONTEXT_ECX_OFFSET (MCONTEXT_GREGS_OFFSET + 10*4)
+#define MCONTEXT_EAX_OFFSET (MCONTEXT_GREGS_OFFSET + 11*4)
+#define MCONTEXT_TRAPNO_OFFSET (MCONTEXT_GREGS_OFFSET + 12*4)
+#define MCONTEXT_ERR_OFFSET (MCONTEXT_GREGS_OFFSET + 13*4)
+#define MCONTEXT_EIP_OFFSET (MCONTEXT_GREGS_OFFSET + 14*4)
+#define MCONTEXT_CS_OFFSET (MCONTEXT_GREGS_OFFSET + 15*4)
+#define MCONTEXT_EFL_OFFSET (MCONTEXT_GREGS_OFFSET + 16*4)
+#define MCONTEXT_UESP_OFFSET (MCONTEXT_GREGS_OFFSET + 17*4)
+#define MCONTEXT_SS_OFFSET (MCONTEXT_GREGS_OFFSET + 18*4)
+
+#define UCONTEXT_SIGMASK_OFFSET 108
+
+#define UCONTEXT_FPREGS_OFFSET 96
+#if defined(__BIONIC__)
+#define UCONTEXT_FPREGS_MEM_OFFSET 116
+#else
+#define UCONTEXT_FPREGS_MEM_OFFSET 236
+#endif
+
+#elif defined(__mips__)
+
+#if _MIPS_SIM == _ABIO32
+#define MCONTEXT_PC_OFFSET 32
+#define MCONTEXT_GREGS_OFFSET 40
+#define MCONTEXT_FPREGS_OFFSET 296
+#define MCONTEXT_FPC_CSR 556
+#define UCONTEXT_SIGMASK_OFFSET 616
+#else
+#define MCONTEXT_GREGS_OFFSET 40
+#define MCONTEXT_FPREGS_OFFSET 296
+#define MCONTEXT_PC_OFFSET 616
+#define MCONTEXT_FPC_CSR 624
+#define UCONTEXT_SIGMASK_OFFSET 640
+#endif
+
+#elif defined(__x86_64__)
+
+#define MCONTEXT_GREGS_OFFSET 40
+#define UCONTEXT_SIGMASK_OFFSET 296
+
+#define MCONTEXT_GREGS_R8 40
+#define MCONTEXT_GREGS_R9 48
+#define MCONTEXT_GREGS_R10 56
+#define MCONTEXT_GREGS_R11 64
+#define MCONTEXT_GREGS_R12 72
+#define MCONTEXT_GREGS_R13 80
+#define MCONTEXT_GREGS_R14 88
+#define MCONTEXT_GREGS_R15 96
+#define MCONTEXT_GREGS_RDI 104
+#define MCONTEXT_GREGS_RSI 112
+#define MCONTEXT_GREGS_RBP 120
+#define MCONTEXT_GREGS_RBX 128
+#define MCONTEXT_GREGS_RDX 136
+#define MCONTEXT_GREGS_RAX 144
+#define MCONTEXT_GREGS_RCX 152
+#define MCONTEXT_GREGS_RSP 160
+#define MCONTEXT_GREGS_RIP 168
+#define MCONTEXT_FPREGS_PTR 224
+#if defined(__BIONIC__)
+#define MCONTEXT_FPREGS_MEM 304
+#else
+#define MCONTEXT_FPREGS_MEM 424
+#endif
+#define FPREGS_OFFSET_MXCSR 24
+
+#else
+#error "This header has not been ported for your CPU"
+#endif
+
+#endif // GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H