13bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki/*
23b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
3772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * honggfuzz - architecture dependent code (LINUX/PTRACE)
4772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * -----------------------------------------
53b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
6772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * Author: Robert Swiecki <swiecki@google.com>
73b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
8772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * Copyright 2010-2015 by Google Inc. All Rights Reserved.
93b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
103b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com * Licensed under the Apache License, Version 2.0 (the "License"); you may
113b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com * not use this file except in compliance with the License. You may obtain
12772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * a copy of the License at
133b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
14772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * http://www.apache.org/licenses/LICENSE-2.0
153b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
16772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * Unless required by applicable law or agreed to in writing, software
17772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * distributed under the License is distributed on an "AS IS" BASIS,
18772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * implied. See the License for the specific language governing
20772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com * permissions and limitations under the License.
213b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com *
22772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com */
233bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
24019de49cb1a0901019839e0218174a0f7bf838e1Robert Swiecki#include "linux/trace.h"
25ba85c3e351a63c68108935d717c24ef20cc32018robert.swiecki@gmail.com
2612fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <ctype.h>
275f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com#include <dirent.h>
2812fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <elf.h>
294c1ad431dc7fbac0308d175e4f7a77ad6912880drobert.swiecki@gmail.com#include <endian.h>
303bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki#include <errno.h>
31ad6af2246b9d25e66266653ed292dc03928df7a5robert.swiecki@gmail.com#include <fcntl.h>
32d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#include <inttypes.h>
3312fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <signal.h>
343bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki#include <stdio.h>
3512fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <stdlib.h>
363bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki#include <string.h>
3712fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <sys/cdefs.h>
3812fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <sys/personality.h>
393bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki#include <sys/ptrace.h>
4012fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <sys/resource.h>
41ad6af2246b9d25e66266653ed292dc03928df7a5robert.swiecki@gmail.com#include <sys/stat.h>
428b76934f112fdbca5cd6b902c1cc503a677bc47cRobert Swiecki#include <sys/syscall.h>
4312fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <sys/time.h>
4412fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <sys/types.h>
45ec3acc56bdc6ad3a682f24d09bcca65bdc8f5e8erobert.swiecki@gmail.com#include <sys/uio.h>
463bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki#include <sys/user.h>
4712fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <sys/wait.h>
4812fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <time.h>
4912fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com#include <unistd.h>
503bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
5110eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "libcommon/common.h"
5210eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "libcommon/files.h"
5310eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "libcommon/log.h"
5410eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "libcommon/util.h"
5510eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "linux/bfd.h"
5610eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "linux/unwind.h"
5710eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "sancov.h"
5810eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "sanitizers.h"
5910eeb0a296350f6e756a736692762a6ce3358d27Robert Swiecki#include "subproc.h"
603bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
61cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#if defined(__ANDROID__)
62cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#include "capstone.h"
63cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#endif
64cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
65cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#if defined(__i386__) || defined(__arm__) || defined(__powerpc__)
66cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#define REG_TYPE uint32_t
67d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#define REG_PM PRIx32
68d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#define REG_PD "0x%08"
69d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki#elif defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \
70d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    defined(__mips__) || defined(__mips64__)
71cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#define REG_TYPE uint64_t
72d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#define REG_PM PRIx64
73d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#define REG_PD "0x%016"
74cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#endif
75cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
76d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis/*
77d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis * Size in characters required to store a string representation of a
78d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis * register value (0xdeadbeef style))
79d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis */
80d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#define REGSIZEINCHAR (2 * sizeof(REG_TYPE) + 3)
81d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis
82cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#if defined(__i386__) || defined(__x86_64__)
83cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#define MAX_INSTR_SZ 16
84cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#elif defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__)
85cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#define MAX_INSTR_SZ 4
86cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#elif defined(__aarch64__)
87cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#define MAX_INSTR_SZ 8
881441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki#elif defined(__mips__) || defined(__mips64__)
891441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki#define MAX_INSTR_SZ 8
90cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#endif
91cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
92cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis#if defined(__i386__) || defined(__x86_64__)
93cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudisstruct user_regs_struct_32 {
94cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t ebx;
95cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t ecx;
96cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t edx;
97cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t esi;
98cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t edi;
99cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t ebp;
100cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t eax;
101cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint16_t ds, __ds;
102cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint16_t es, __es;
103cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint16_t fs, __fs;
104cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint16_t gs, __gs;
105cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t orig_eax;
106cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t eip;
107cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint16_t cs, __cs;
108cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t eflags;
109cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t esp;
110cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint16_t ss, __ss;
111cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis};
112cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
113cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudisstruct user_regs_struct_64 {
114cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r15;
115cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r14;
116cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r13;
117cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r12;
118cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t bp;
119cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t bx;
120cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r11;
121cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r10;
122cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r9;
123cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t r8;
124cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t ax;
125cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t cx;
126cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t dx;
127cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t si;
128cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t di;
129cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t orig_ax;
130cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t ip;
131cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t cs;
132cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t flags;
133cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t sp;
134cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t ss;
135cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t fs_base;
136cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t gs_base;
137cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t ds;
138cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t es;
139cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t fs;
140cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t gs;
141cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis};
142cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis#define HEADERS_STRUCT struct user_regs_struct_64
1434e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__i386__) || defined(__x86_64__) */
144cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
14517887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#if defined(__arm__) || defined(__aarch64__)
146d628a709694488a860974063c8b44f33e82d7ec2Jagger#ifndef ARM_pc
1474e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#ifdef __ANDROID__ /* Building with NDK headers */
148d628a709694488a860974063c8b44f33e82d7ec2Jagger#define ARM_pc uregs[15]
1494e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#else /* Building with glibc headers */
150d628a709694488a860974063c8b44f33e82d7ec2Jagger#define ARM_pc 15
151d628a709694488a860974063c8b44f33e82d7ec2Jagger#endif
1524e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* ARM_pc */
153d628a709694488a860974063c8b44f33e82d7ec2Jagger#ifndef ARM_cpsr
1544e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#ifdef __ANDROID__ /* Building with NDK headers */
155d628a709694488a860974063c8b44f33e82d7ec2Jagger#define ARM_cpsr uregs[16]
1564e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#else /* Building with glibc headers */
157d628a709694488a860974063c8b44f33e82d7ec2Jagger#define ARM_cpsr 16
158d628a709694488a860974063c8b44f33e82d7ec2Jagger#endif
1594e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* ARM_cpsr */
160cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudisstruct user_regs_struct_32 {
161cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t uregs[18];
162cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis};
163cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
164cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudisstruct user_regs_struct_64 {
165cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t regs[31];
166cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t sp;
167cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t pc;
168cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t pstate;
169cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis};
17017887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#define HEADERS_STRUCT struct user_regs_struct_64
1714e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__arm__) || defined(__aarch64__) */
172cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
173cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis#if defined(__powerpc64__) || defined(__powerpc__)
174cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis#define HEADERS_STRUCT struct pt_regs
175cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudisstruct user_regs_struct_32 {
176cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t gpr[32];
177cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t nip;
178cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t msr;
179cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t orig_gpr3;
180cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t ctr;
181cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t link;
182cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t xer;
183cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t ccr;
184cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t mq;
185cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t trap;
186cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t dar;
187cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t dsisr;
188cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t result;
189cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    /*
190cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     * elf.h's ELF_NGREG says it's 48 registers, so kernel fills it in
191cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     * with some zeros
192cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     */
193cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t zero0;
194cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t zero1;
195cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t zero2;
196cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint32_t zero3;
197cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis};
198cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudisstruct user_regs_struct_64 {
199cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t gpr[32];
200cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t nip;
201cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t msr;
202cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t orig_gpr3;
203cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t ctr;
204cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t link;
205cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t xer;
206cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t ccr;
207cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t softe;
208cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t trap;
209cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t dar;
210cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t dsisr;
211cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t result;
212cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    /*
213cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     * elf.h's ELF_NGREG says it's 48 registers, so kernel fills it in
214cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     * with some zeros
215cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     */
216cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t zero0;
217cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t zero1;
218cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t zero2;
219cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    uint64_t zero3;
220cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis};
2214e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__powerpc64__) || defined(__powerpc__) */
222cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
2231441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki#if defined(__mips__) || defined(__mips64__)
2241441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swieckistruct user_regs_struct {
2251441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t regs[32];
2261441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki
2271441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t lo;
2281441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t hi;
2291441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t cp0_epc;
2301441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t cp0_badvaddr;
2311441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t cp0_status;
2321441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    uint64_t cp0_cause;
2331441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki};
2341441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki#define HEADERS_STRUCT struct user_regs_struct
2354e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__mips__) || defined(__mips64__) */
2361441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki
237cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#if defined(__ANDROID__)
23823ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki/*
2396d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis * Some Android ABIs don't implement PTRACE_GETREGS (e.g. aarch64)
240cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis */
2416d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#if defined(PTRACE_GETREGS)
2426d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#define PTRACE_GETREGS_AVAILABLE 1
2436d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#else
2446d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#define PTRACE_GETREGS_AVAILABLE 0
2454e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(PTRACE_GETREGS) */
2464e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__ANDROID__) */
247cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
248e84b645dcff103f9bd80b2be15c784e8bf736d0eRobert Swieckistatic struct {
249d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki    const char* descr;
2501f2d5b194a249716fbd6f094cc335c751767fb99Jagger    bool important;
251e84b645dcff103f9bd80b2be15c784e8bf736d0eRobert Swiecki} arch_sigs[_NSIG + 1] = {
2524e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    [0 ...(_NSIG)].important = false,
253d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki    [0 ...(_NSIG)].descr = "UNKNOWN",
254b16e1d9511616c7d91710cc35ca32ca33b653d38robert.swiecki@gmail.com
255dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    [SIGTRAP].important = false,
256dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    [SIGTRAP].descr = "SIGTRAP",
2571f2d5b194a249716fbd6f094cc335c751767fb99Jagger
25834a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGILL].important = true,
25934a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGILL].descr = "SIGILL",
2601f2d5b194a249716fbd6f094cc335c751767fb99Jagger
26134a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGFPE].important = true,
26234a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGFPE].descr = "SIGFPE",
2631f2d5b194a249716fbd6f094cc335c751767fb99Jagger
26434a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGSEGV].important = true,
26534a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGSEGV].descr = "SIGSEGV",
2661f2d5b194a249716fbd6f094cc335c751767fb99Jagger
26734a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGBUS].important = true,
26834a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com    [SIGBUS].descr = "SIGBUS",
2691f2d5b194a249716fbd6f094cc335c751767fb99Jagger
270f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis    /* Is affected from monitorSIGABRT flag */
2718e634c3ef96143be77e8beaaa5620e3fdf41dcd5Anestis Bechtsoudis    [SIGABRT].important = false,
272e84b645dcff103f9bd80b2be15c784e8bf736d0eRobert Swiecki    [SIGABRT].descr = "SIGABRT",
273e84b645dcff103f9bd80b2be15c784e8bf736d0eRobert Swiecki
274eba27171213942cb463e68f04ad2f2b70012d106Robert Swiecki    /* Is affected from tmoutVTALRM flag */
275f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis    [SIGVTALRM].important = false,
276e84b645dcff103f9bd80b2be15c784e8bf736d0eRobert Swiecki    [SIGVTALRM].descr = "SIGVTALRM-TMOUT",
27749028c9d1a4397b2e02415b164e4d8fd07571016Robert Swiecki
27849028c9d1a4397b2e02415b164e4d8fd07571016Robert Swiecki    /* seccomp-bpf kill */
27949028c9d1a4397b2e02415b164e4d8fd07571016Robert Swiecki    [SIGSYS].important = true,
28049028c9d1a4397b2e02415b164e4d8fd07571016Robert Swiecki    [SIGSYS].descr = "SIGSYS",
28134a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com};
2823bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
2838d95df7617521689db58fb6f6e4373549a54cb75Anestis Bechtsoudis#ifndef SI_FROMUSER
284d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
2854e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* SI_FROMUSER */
2868d95df7617521689db58fb6f6e4373549a54cb75Anestis Bechtsoudis
2874e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swieckiextern const char* sys_sigabbrev[];
288bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki
289bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swieckistatic __thread char arch_signame[32];
290d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic const char* arch_sigName(int signo) {
291bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki    if (signo < 0 || signo > _NSIG) {
292bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki        snprintf(arch_signame, sizeof(arch_signame), "UNKNOWN-%d", signo);
293bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki        return arch_signame;
294bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki    }
295bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki    if (signo > __SIGRTMIN) {
296bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki        snprintf(arch_signame, sizeof(arch_signame), "SIG%d-RTMIN+%d", signo, signo - __SIGRTMIN);
297bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki        return arch_signame;
298bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki    }
299bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki#ifdef __ANDROID__
300bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki    return arch_sigs[signo].descr;
301bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki#else
302cd3d0c5ff7a32aa6d080555a1b6a43f73d502391Robert Swiecki    if (sys_sigabbrev[signo] == NULL) {
303cd3d0c5ff7a32aa6d080555a1b6a43f73d502391Robert Swiecki        snprintf(arch_signame, sizeof(arch_signame), "SIG%d", signo);
304cd3d0c5ff7a32aa6d080555a1b6a43f73d502391Robert Swiecki    } else {
305cd3d0c5ff7a32aa6d080555a1b6a43f73d502391Robert Swiecki        snprintf(arch_signame, sizeof(arch_signame), "SIG%s", sys_sigabbrev[signo]);
306cd3d0c5ff7a32aa6d080555a1b6a43f73d502391Robert Swiecki    }
307bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki    return arch_signame;
3084e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* __ANDROID__ */
309bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki}
310bfbc78b1d1c64a6da925f665b8891a0fee1080cdRobert Swiecki
311d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic size_t arch_getProcMem(pid_t pid, uint8_t* buf, size_t len, REG_TYPE pc) {
312772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com    /*
3133b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com     * Let's try process_vm_readv first
314772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com     */
315ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    const struct iovec local_iov = {
316ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com        .iov_base = buf,
317ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com        .iov_len = len,
318ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    };
319ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    const struct iovec remote_iov = {
3204e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        .iov_base = (void*)(uintptr_t)pc,
321ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com        .iov_len = len,
322ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    };
3234e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    if (process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0) == (ssize_t)len) {
324ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com        return len;
325ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    }
326cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    // Debug if failed since it shouldn't happen very often
327c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki    PLOG_D("process_vm_readv() failed");
328cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
3293bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    /*
330ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com     * Ok, let's do it via ptrace() then.
3313bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     * len must be aligned to the sizeof(long)
3323bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     */
3333bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    int cnt = len / sizeof(long);
3343bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    size_t memsz = 0;
3353bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
3363bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    for (int x = 0; x < cnt; x++) {
3374e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        uint8_t* addr = (uint8_t*)(uintptr_t)pc + (int)(x * sizeof(long));
338a0df592ba4f3ed3c1c04efbe422caa9c380c7053Jagger        long ret = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
3393bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
3403bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        if (errno != 0) {
341c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki            PLOG_W("Couldn't PT_READ_D on pid %d, addr: %p", pid, addr);
3423bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki            break;
3433bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        }
3443bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
3453bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        memsz += sizeof(long);
3463bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        memcpy(&buf[x * sizeof(long)], &ret, sizeof(long));
3473bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
3483bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    return memsz;
3493bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki}
3503bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
351d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic size_t arch_getPC(pid_t pid, REG_TYPE* pc, REG_TYPE* status_reg UNUSED) {
3524021d12859c2517ffd379fafe00617b22b84d6c1Robert Swiecki/*
3530b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki * Some old ARM android kernels are failing with PTRACE_GETREGS to extract
3540b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki * the correct register values if struct size is bigger than expected. As such the
3550b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki * 32/64-bit multiplexing trick is not working for them in case PTRACE_GETREGSET
3560b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki * fails or is not implemented. To cover such cases we explicitly define
3570b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki * the struct size to 32bit version for arm CPU.
3580b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki */
359672a9180036242d16d83bc77347834228a7bbe29Anestis Bechtsoudis#if defined(__arm__)
360672a9180036242d16d83bc77347834228a7bbe29Anestis Bechtsoudis    struct user_regs_struct_32 regs;
361672a9180036242d16d83bc77347834228a7bbe29Anestis Bechtsoudis#else
362cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    HEADERS_STRUCT regs;
363672a9180036242d16d83bc77347834228a7bbe29Anestis Bechtsoudis#endif
364ec3acc56bdc6ad3a682f24d09bcca65bdc8f5e8erobert.swiecki@gmail.com    struct iovec pt_iov = {
365cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis        .iov_base = &regs,
366cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis        .iov_len = sizeof(regs),
367ec3acc56bdc6ad3a682f24d09bcca65bdc8f5e8erobert.swiecki@gmail.com    };
368cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
3698a7d698c26084d21ade1cb044da721540bfc1706robert.swiecki@gmail.com    if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &pt_iov) == -1L) {
370c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        PLOG_D("ptrace(PTRACE_GETREGSET) failed");
37117887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis
3724021d12859c2517ffd379fafe00617b22b84d6c1Robert Swiecki// If PTRACE_GETREGSET fails, try PTRACE_GETREGS if available
3736d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#if PTRACE_GETREGS_AVAILABLE
374cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis        if (ptrace(PTRACE_GETREGS, pid, 0, &regs)) {
375c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki            PLOG_D("ptrace(PTRACE_GETREGS) failed");
376d81f09724246b794d5acccde2e008c9d12d9c4edAnestis Bechtsoudis            LOG_W("ptrace PTRACE_GETREGSET & PTRACE_GETREGS failed to extract target registers");
37717887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis            return 0;
378cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis        }
3796d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#else
3806d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis        return 0;
3816d8d612b6ea0d3cec3502de8976d7c481672eca0Anestis Bechtsoudis#endif
382ec3acc56bdc6ad3a682f24d09bcca65bdc8f5e8erobert.swiecki@gmail.com    }
383cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis#if defined(__i386__) || defined(__x86_64__)
384772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com    /*
3853b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com     * 32-bit
386772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com     */
387ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    if (pt_iov.iov_len == sizeof(struct user_regs_struct_32)) {
3884e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct user_regs_struct_32* r32 = (struct user_regs_struct_32*)&regs;
389730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com        *pc = r32->eip;
390cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        *status_reg = r32->eflags;
39117887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        return pt_iov.iov_len;
392ec3acc56bdc6ad3a682f24d09bcca65bdc8f5e8erobert.swiecki@gmail.com    }
393cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
394772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com    /*
3953b630b47e7d39e7b36c749290385e284bc5eb950robert.swiecki@gmail.com     * 64-bit
396772b33d10d4225a4befcb557ffbea889ad891958robert.swiecki@gmail.com     */
397ae20f60e3af7cb3bea4943b53a1f3e35d9fe1eb0robert.swiecki@gmail.com    if (pt_iov.iov_len == sizeof(struct user_regs_struct_64)) {
3984e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct user_regs_struct_64* r64 = (struct user_regs_struct_64*)&regs;
399730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com        *pc = r64->ip;
400cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        *status_reg = r64->flags;
40117887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        return pt_iov.iov_len;
402ec3acc56bdc6ad3a682f24d09bcca65bdc8f5e8erobert.swiecki@gmail.com    }
403c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki    LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len);
40417887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    return 0;
4054e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__i386__) || defined(__x86_64__) */
406cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
40717887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#if defined(__arm__) || defined(__aarch64__)
40817887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    /*
40917887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis     * 32-bit
41017887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis     */
411730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    if (pt_iov.iov_len == sizeof(struct user_regs_struct_32)) {
4124e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct user_regs_struct_32* r32 = (struct user_regs_struct_32*)&regs;
413cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#ifdef __ANDROID__
414cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        *pc = r32->ARM_pc;
415cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        *status_reg = r32->ARM_cpsr;
416cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#else
417730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com        *pc = r32->uregs[ARM_pc];
418cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        *status_reg = r32->uregs[ARM_cpsr];
419cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#endif
42017887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        return pt_iov.iov_len;
421730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    }
422cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
42317887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    /*
42417887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis     * 64-bit
42517887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis     */
426730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    if (pt_iov.iov_len == sizeof(struct user_regs_struct_64)) {
4274e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct user_regs_struct_64* r64 = (struct user_regs_struct_64*)&regs;
428730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com        *pc = r64->pc;
429cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        *status_reg = r64->pstate;
43017887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        return pt_iov.iov_len;
431730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    }
432b48b4744ce83120f3ef979f58ccab70a15f06762Anestis Bechtsoudis    LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len);
43317887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    return 0;
4344e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__arm__) || defined(__aarch64__) */
435cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
436730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com#if defined(__powerpc64__) || defined(__powerpc__)
437cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    /*
438cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     * 32-bit
439cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     */
440730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    if (pt_iov.iov_len == sizeof(struct user_regs_struct_32)) {
4414e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct user_regs_struct_32* r32 = (struct user_regs_struct_32*)&regs;
442730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com        *pc = r32->nip;
44317887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        return pt_iov.iov_len;
444730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    }
445cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
446cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis    /*
447cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     * 64-bit
448cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis     */
449730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    if (pt_iov.iov_len == sizeof(struct user_regs_struct_64)) {
4504e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct user_regs_struct_64* r64 = (struct user_regs_struct_64*)&regs;
451730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com        *pc = r64->nip;
45217887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        return pt_iov.iov_len;
453730f9486a4292fc6c94c29b3730cb87edc8cdb4brobert.swiecki@gmail.com    }
454cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
455b48b4744ce83120f3ef979f58ccab70a15f06762Anestis Bechtsoudis    LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len);
45617887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    return 0;
4574e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__powerpc64__) || defined(__powerpc__) */
458cab40dea61c8bbe0d3a291fed4ef33a95135a33eAnestis Bechtsoudis
4591441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki#if defined(__mips__) || defined(__mips64__)
4601441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    *pc = regs.cp0_epc;
4611441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki    return pt_iov.iov_len;
4624e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__mips__) || defined(__mips64__) */
4631441b6bb52013236da04b61b6b06c48e4b6f36f5Robert Swiecki
464c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki    LOG_D("Unknown/unsupported CPU architecture");
46517887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    return 0;
46612fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com}
46712fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com
468d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_getInstrStr(pid_t pid, REG_TYPE* pc, char* instr) {
4693bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    /*
47034a4070a273f9f64ee42053677d0632576ddfbd0robert.swiecki@gmail.com     * We need a value aligned to 8
4713bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     * which is sizeof(long) on 64bit CPU archs (on most of them, I hope;)
4723bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     */
473cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    uint8_t buf[MAX_INSTR_SZ];
4743bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    size_t memsz;
475cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    REG_TYPE status_reg = 0;
476cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
4779e2d43de38ba979258bedf81b7a65f98bd0af929robert.swiecki@gmail.com    snprintf(instr, _HF_INSTR_SZ, "%s", "[UNKNOWN]");
47812fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com
47917887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    size_t pcRegSz = arch_getPC(pid, pc, &status_reg);
48017887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    if (!pcRegSz) {
481c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_W("Current architecture not supported for disassembly");
48212fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com        return;
48312fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com    }
48412fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com
48512fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com    if ((memsz = arch_getProcMem(pid, buf, sizeof(buf), *pc)) == 0) {
4869e2d43de38ba979258bedf81b7a65f98bd0af929robert.swiecki@gmail.com        snprintf(instr, _HF_INSTR_SZ, "%s", "[NOT_MMAPED]");
4873bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        return;
4883bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
489cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#if !defined(__ANDROID__)
49026eee243813ffb12957e386d9475d7d4a9d9b245robert.swiecki@gmail.com    arch_bfdDisasm(pid, buf, memsz, instr);
491cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#else
49217887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    cs_arch arch;
49317887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    cs_mode mode;
49417887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#if defined(__arm__) || defined(__aarch64__)
49517887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    arch = (pcRegSz == sizeof(struct user_regs_struct_64)) ? CS_ARCH_ARM64 : CS_ARCH_ARM;
49617887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    if (arch == CS_ARCH_ARM) {
49717887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        mode = (status_reg & 0x20) ? CS_MODE_THUMB : CS_MODE_ARM;
498d628a709694488a860974063c8b44f33e82d7ec2Jagger    } else {
49917887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis        mode = CS_MODE_ARM;
500d628a709694488a860974063c8b44f33e82d7ec2Jagger    }
50117887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#elif defined(__i386__) || defined(__x86_64__)
50217887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    arch = CS_ARCH_X86;
50317887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    mode = (pcRegSz == sizeof(struct user_regs_struct_64)) ? CS_MODE_64 : CS_MODE_32;
504cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#else
505e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    LOG_E("Unknown/Unsupported Android CPU architecture");
506cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#endif
507cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
508cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    csh handle;
509cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    cs_err err = cs_open(arch, mode, &handle);
510cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    if (err != CS_ERR_OK) {
511c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_W("Capstone initialization failed: '%s'", cs_strerror(err));
512cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        return;
513cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    }
514cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
5154e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    cs_insn* insn;
516cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    size_t count = cs_disasm(handle, buf, sizeof(buf), *pc, 0, &insn);
517cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
518cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    if (count < 1) {
519c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_W("Couldn't disassemble the assembler instructions' stream: '%s'",
5204e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki            cs_strerror(cs_errno(handle)));
521cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        cs_close(&handle);
522cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        return;
523cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    }
524cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
525cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    snprintf(instr, _HF_INSTR_SZ, "%s %s", insn[0].mnemonic, insn[0].op_str);
526cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    cs_free(insn, count);
527cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    cs_close(&handle);
5284e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* defined(__ANDROID__) */
529cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis
5309e2d43de38ba979258bedf81b7a65f98bd0af929robert.swiecki@gmail.com    for (int x = 0; instr[x] && x < _HF_INSTR_SZ; x++) {
5310b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki        if (instr[x] == '/' || instr[x] == '\\' || isspace(instr[x]) || !isprint(instr[x])) {
5323bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki            instr[x] = '_';
5333bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        }
5343bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
53526eee243813ffb12957e386d9475d7d4a9d9b245robert.swiecki@gmail.com
53626eee243813ffb12957e386d9475d7d4a9d9b245robert.swiecki@gmail.com    return;
5373bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki}
5383bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
539d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_hashCallstack(run_t* run, funcs_t* funcs, size_t funcCnt, bool enableMasking) {
540d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    uint64_t hash = 0;
54178633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    for (size_t i = 0; i < funcCnt && i < run->global->linux.numMajorFrames; i++) {
542d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis        /*
543d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis         * Convert PC to char array to be compatible with hash function
544d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis         */
545d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki        char pcStr[REGSIZEINCHAR] = {0};
5464e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        snprintf(pcStr, REGSIZEINCHAR, REG_PD REG_PM, (REG_TYPE)(long)funcs[i].pc);
547d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis
548d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis        /*
549d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis         * Hash the last three nibbles
550d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis         */
551d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis        hash ^= util_hash(&pcStr[strlen(pcStr) - 3], 3);
552d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    }
553d3ffe9eeebf753e451c63febb7590d383e395e02Anestis Bechtsoudis
554d3ffe9eeebf753e451c63febb7590d383e395e02Anestis Bechtsoudis    /*
55560ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis     * If only one frame, hash is not safe to be used for uniqueness. We mask it
55660ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis     * here with a constant prefix, so analyzers can pick it up and create filenames
55760ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis     * accordingly. 'enableMasking' is controlling masking for cases where it should
55860ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis     * not be enabled (e.g. fuzzer worker is from verifier).
559d3ffe9eeebf753e451c63febb7590d383e395e02Anestis Bechtsoudis     */
560d3ffe9eeebf753e451c63febb7590d383e395e02Anestis Bechtsoudis    if (enableMasking && funcCnt == 1) {
561c06f8b33adf90032a34508c190923d82fa99f398Anestis Bechtsoudis        hash |= _HF_SINGLE_FRAME_MASK;
562d3ffe9eeebf753e451c63febb7590d383e395e02Anestis Bechtsoudis    }
563e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    run->backtrace = hash;
564d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis}
565d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis
5660b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swieckistatic void arch_traceGenerateReport(
567d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    pid_t pid, run_t* run, funcs_t* funcs, size_t funcCnt, siginfo_t* si, const char* instr) {
568e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    run->report[0] = '\0';
569e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "ORIG_FNAME: %s\n", run->origFileName);
570e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "FUZZ_FNAME: %s\n", run->crashFileName);
571e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "PID: %d\n", pid);
572e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "SIGNAL: %s (%d)\n",
5734e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        arch_sigName(si->si_signo), si->si_signo);
574e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "FAULT ADDRESS: %p\n",
5754e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        SI_FROMUSER(si) ? NULL : si->si_addr);
576e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "INSTRUCTION: %s\n", instr);
577e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "STACK HASH: %016llx\n", run->backtrace);
578e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "STACK:\n");
579576232be18a657a5e08da39d52beffaacafe46b1robert.swiecki@gmail.com    for (size_t i = 0; i < funcCnt; i++) {
580cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#ifdef __HF_USE_CAPSTONE__
581e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        util_ssnprintf(
582e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            run->report, sizeof(run->report), " <" REG_PD REG_PM "> ", (REG_TYPE)(long)funcs[i].pc);
583cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        if (funcs[i].func[0] != '\0')
584e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            util_ssnprintf(run->report, sizeof(run->report), "[%s() + 0x%x at %s]\n", funcs[i].func,
585e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki                funcs[i].line, funcs[i].mapName);
586cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis        else
587e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            util_ssnprintf(run->report, sizeof(run->report), "[]\n");
588cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#else
589e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        util_ssnprintf(run->report, sizeof(run->report), " <" REG_PD REG_PM "> [%s():%u at %s]\n",
590e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            (REG_TYPE)(long)funcs[i].pc, funcs[i].func, funcs[i].line, funcs[i].mapName);
591cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis#endif
592576232be18a657a5e08da39d52beffaacafe46b1robert.swiecki@gmail.com    }
593576232be18a657a5e08da39d52beffaacafe46b1robert.swiecki@gmail.com
5944021d12859c2517ffd379fafe00617b22b84d6c1Robert Swiecki// libunwind is not working for 32bit targets in 64bit systems
59517887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#if defined(__aarch64__)
59617887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    if (funcCnt == 0) {
597e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        util_ssnprintf(run->report, sizeof(run->report),
5980b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki            " !ERROR: If 32bit fuzz target"
5990b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki            " in aarch64 system, try ARM 32bit build\n");
60017887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis    }
60117887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis#endif
60217887e2503e8e99d1ee151bfa468d47f426866abAnestis Bechtsoudis
603576232be18a657a5e08da39d52beffaacafe46b1robert.swiecki@gmail.com    return;
604576232be18a657a5e08da39d52beffaacafe46b1robert.swiecki@gmail.com}
605576232be18a657a5e08da39d52beffaacafe46b1robert.swiecki@gmail.com
606d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_traceAnalyzeData(run_t* run, pid_t pid) {
607c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    REG_TYPE pc = 0, status_reg = 0;
608c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    size_t pcRegSz = arch_getPC(pid, &pc, &status_reg);
609c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    if (!pcRegSz) {
610c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        LOG_W("ptrace arch_getPC failed");
611c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        return;
612c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    }
613c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis
6145c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis    /*
6155c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis     * Unwind and resolve symbols
6165c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis     */
6174e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t));
6180b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { free(funcs); };
6196fb025e8c04bfec166ade14046458f124f3e344cAnestis Bechtsoudis    memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t));
6205c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis
6215c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis#if !defined(__ANDROID__)
6225c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis    size_t funcCnt = arch_unwindStack(pid, funcs);
6235c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis    arch_bfdResolveSyms(pid, funcs, funcCnt);
6245c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis#else
6255c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis    size_t funcCnt = arch_unwindStack(pid, funcs);
6265c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis#endif
6275c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis
62823ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
62923ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki     * If unwinder failed (zero frames), use PC from ptrace GETREGS if not zero.
630c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis     * If PC reg zero return and callers should handle zero hash case.
631c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis     */
632c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    if (funcCnt == 0) {
633c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        if (pc) {
634c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis            /* Manually update major frame PC & frames counter */
6354e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki            funcs[0].pc = (void*)(uintptr_t)pc;
636c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis            funcCnt = 1;
637c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        } else {
638c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis            return;
639c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        }
640c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    }
641c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis
6425c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis    /*
6435c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis     * Calculate backtrace callstack hash signature
6445c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis     */
64578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    arch_hashCallstack(run, funcs, funcCnt, false);
6465c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis}
6475c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis
648d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_traceSaveData(run_t* run, pid_t pid) {
649cfc39fb203a5e14915dee874957487935554d23bAnestis Bechtsoudis    REG_TYPE pc = 0;
65036068adbbe41bc8b9f2a7ca2052e8cb2c3542f4fAnestis Bechtsoudis
65136068adbbe41bc8b9f2a7ca2052e8cb2c3542f4fAnestis Bechtsoudis    /* Local copy since flag is overridden for some crashes */
65226fd6d58dfabe2d047d422c1098794980d59dad2Robert Swiecki    bool saveUnique = run->global->io.saveUnique;
6533bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
6549e2d43de38ba979258bedf81b7a65f98bd0af929robert.swiecki@gmail.com    char instr[_HF_INSTR_SZ] = "\x00";
6553bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    siginfo_t si;
656dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    bzero(&si, sizeof(si));
6573bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
658a0df592ba4f3ed3c1c04efbe422caa9c380c7053Jagger    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == -1) {
659c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        PLOG_W("Couldn't get siginfo for pid %d", pid);
6603bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
6613bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
66212fbf549cb142fa18650f8a6a780c1a69dabf6f0robert.swiecki@gmail.com    arch_getInstrStr(pid, &pc, instr);
6633bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
664d0fa62c5606ba9caf914b4db031d22d9551d16baRobert Swiecki    LOG_D("Pid: %d, signo: %d, errno: %d, code: %d, addr: %p, pc: %" REG_PM ", instr: '%s'", pid,
6654e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        si.si_signo, si.si_errno, si.si_code, si.si_addr, pc, instr);
6663bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
66778633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (!SI_FROMUSER(&si) && pc && si.si_addr < run->global->linux.ignoreAddr) {
668c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_I("'%s' is interesting (%s), but the si.si_addr is %p (below %p), skipping",
66978633d1b907775e7067fb04332859703de72ac3fRobert Swiecki            run->fileName, arch_sigName(si.si_signo), si.si_addr, run->global->linux.ignoreAddr);
6703bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        return;
6713bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
6723bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
673d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    /*
674d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis     * Unwind and resolve symbols
675d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis     */
6764e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t));
6770b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { free(funcs); };
6786fb025e8c04bfec166ade14046458f124f3e344cAnestis Bechtsoudis    memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t));
679d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis
680d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis#if !defined(__ANDROID__)
681d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    size_t funcCnt = arch_unwindStack(pid, funcs);
682d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    arch_bfdResolveSyms(pid, funcs, funcCnt);
683d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis#else
684d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    size_t funcCnt = arch_unwindStack(pid, funcs);
685d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis#endif
686d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis
68723ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
68823ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki     * If unwinder failed (zero frames), use PC from ptrace GETREGS if not zero.
689c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis     * If PC reg zero, temporarily disable uniqueness flag since callstack
690c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis     * hash will be also zero, thus not safe for unique decisions.
691c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis     */
692c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    if (funcCnt == 0) {
693c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        if (pc) {
694c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis            /* Manually update major frame PC & frames counter */
6954e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki            funcs[0].pc = (void*)(uintptr_t)pc;
696c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis            funcCnt = 1;
697c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        } else {
698c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis            saveUnique = false;
699c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis        }
700c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis    }
701c45db7fc0013ac67e4ac98add8f4278e1aa2f93cAnestis Bechtsoudis
70223ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
7032013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis     * Temp local copy of previous backtrace value in case worker hit crashes into multiple
7042013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis     * tids for same target master thread. Will be 0 for first crash against target.
7052013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis     */
706e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    uint64_t oldBacktrace = run->backtrace;
7072013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis
708d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis    /*
709d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis     * Calculate backtrace callstack hash signature
710d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis     */
71178633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    arch_hashCallstack(run, funcs, funcCnt, saveUnique);
712d4b8fe91d8f0cc84e2b499fa4057c420b2b74f59Anestis Bechtsoudis
713a16f70fd00bbfe175cff200fb3b95a28e741760aAnestis Bechtsoudis    /*
714a16f70fd00bbfe175cff200fb3b95a28e741760aAnestis Bechtsoudis     * If fuzzing with sanitizer coverage feedback increase crashes counter used
715a16f70fd00bbfe175cff200fb3b95a28e741760aAnestis Bechtsoudis     * as metric for dynFile evolution
716a16f70fd00bbfe175cff200fb3b95a28e741760aAnestis Bechtsoudis     */
71778633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->useSanCov) {
718e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        run->sanCovCnts.crashesCnt++;
719a16f70fd00bbfe175cff200fb3b95a28e741760aAnestis Bechtsoudis    }
720a16f70fd00bbfe175cff200fb3b95a28e741760aAnestis Bechtsoudis
72123ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
72223ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki     * If unique flag is set and single frame crash, disable uniqueness for this crash
72360ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis     * to always save (timestamp will be added to the filename)
72460ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis     */
72536068adbbe41bc8b9f2a7ca2052e8cb2c3542f4fAnestis Bechtsoudis    if (saveUnique && (funcCnt == 1)) {
72660ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis        saveUnique = false;
7270ef9000a3c6de8154989e7777c332d48bb2b9c38Anestis Bechtsoudis    }
7280ef9000a3c6de8154989e7777c332d48bb2b9c38Anestis Bechtsoudis
72923ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
7302013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis     * If worker crashFileName member is set, it means that a tid has already crashed
7312013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis     * from target master thread.
7322013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis     */
733e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    if (run->crashFileName[0] != '\0') {
7342013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis        LOG_D("Multiple crashes detected from worker against attached tids group");
73525262b3dbda4ddc7182ccdb2cf8965ed69ca8ea6Anestis Bechtsoudis
7362013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis        /*
7372013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis         * If stackhashes match, don't re-analyze. This will avoid duplicates
7382013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis         * and prevent verifier from running multiple passes. Depth of check is
7392013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis         * always 1 (last backtrace saved only per target iteration).
7402013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis         */
741e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        if (oldBacktrace == run->backtrace) {
7422013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis            return;
7432013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis        }
7442013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis    }
7452013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis
7462013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis    /* Increase global crashes counter */
7472542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki    ATOMIC_POST_INC(run->global->cnts.crashesCnt);
7482013f25a0d1c7e8355a696cd2c396e2e32c86adfAnestis Bechtsoudis
74923ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
750ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis     * Check if backtrace contains whitelisted symbol. Whitelist overrides
751ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis     * both stackhash and symbol blacklist. Crash is always kept regardless
752ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis     * of the status of uniqueness flag.
753d59af69918025f45fd346abed60370cf69c30eebAnestis Bechtsoudis     */
75478633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->linux.symsWl) {
75578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki        char* wlSymbol = arch_btContainsSymbol(
75678633d1b907775e7067fb04332859703de72ac3fRobert Swiecki            run->global->linux.symsWlCnt, run->global->linux.symsWl, funcCnt, funcs);
757ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        if (wlSymbol != NULL) {
758ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis            saveUnique = false;
759ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis            LOG_D("Whitelisted symbol '%s' found, skipping blacklist checks", wlSymbol);
760ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        }
761ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis    } else {
762ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        /*
763ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis         * Check if stackhash is blacklisted
764ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis         */
765d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki        if (run->global->blacklist && (fastArray64Search(run->global->blacklist,
766d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                                           run->global->blacklistCnt, run->backtrace) != -1)) {
767e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", run->backtrace);
7682542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki            ATOMIC_POST_INC(run->global->cnts.blCrashesCnt);
769ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis            return;
770ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        }
771ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis
772ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        /*
773ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis         * Check if backtrace contains blacklisted symbol
774ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis         */
77578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki        char* blSymbol = arch_btContainsSymbol(
77678633d1b907775e7067fb04332859703de72ac3fRobert Swiecki            run->global->linux.symsBlCnt, run->global->linux.symsBl, funcCnt, funcs);
777ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        if (blSymbol != NULL) {
778ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis            LOG_I("Blacklisted symbol '%s' found, skipping", blSymbol);
7792542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki            ATOMIC_POST_INC(run->global->cnts.blCrashesCnt);
780ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis            return;
781ba68b38c475614a7f7193533e03adfd464cfd450Anestis Bechtsoudis        }
782d59af69918025f45fd346abed60370cf69c30eebAnestis Bechtsoudis    }
783d59af69918025f45fd346abed60370cf69c30eebAnestis Bechtsoudis
7845a311410960d771264787b9118ee30ca7affb172Anestis Bechtsoudis    /* If non-blacklisted crash detected, zero set two MSB */
78578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    ATOMIC_POST_ADD(run->global->dynFileIterExpire, _HF_DYNFILE_SUB_MASK);
7865a311410960d771264787b9118ee30ca7affb172Anestis Bechtsoudis
7874e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    void* sig_addr = si.si_addr;
78878633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->linux.disableRandomization == false) {
7891f2d5b194a249716fbd6f094cc335c751767fb99Jagger        pc = 0UL;
7901f2d5b194a249716fbd6f094cc335c751767fb99Jagger        sig_addr = NULL;
7911f2d5b194a249716fbd6f094cc335c751767fb99Jagger    }
7921f2d5b194a249716fbd6f094cc335c751767fb99Jagger
793d08c85024fa513431fdf16770067420834b76814Jagger    /* User-induced signals don't set si.si_addr */
794d08c85024fa513431fdf16770067420834b76814Jagger    if (SI_FROMUSER(&si)) {
7951011c9e23075da1e3246eaeb7a245144dbc1957cJagger        sig_addr = NULL;
7961011c9e23075da1e3246eaeb7a245144dbc1957cJagger    }
7971f2d5b194a249716fbd6f094cc335c751767fb99Jagger
79846ea10e4663744661c4a772e95110745dafec5e3Anestis Bechtsoudis    /* If dry run mode, copy file with same name into workspace */
79978633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->mutationsPerRun == 0U && run->global->useVerifier) {
800ced3ebaa5a4a96185dc92a40c98f6dbb8728743bRobert Swiecki        snprintf(run->crashFileName, sizeof(run->crashFileName), "%s/%s", run->global->io.crashDir,
801e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            run->origFileName);
80260ea5e7dd1d45013f7ce63afd6faa9333ea7bc3aAnestis Bechtsoudis    } else if (saveUnique) {
803e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        snprintf(run->crashFileName, sizeof(run->crashFileName),
80478633d1b907775e7067fb04332859703de72ac3fRobert Swiecki            "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%d.ADDR.%p.INSTR.%s.%s",
805ced3ebaa5a4a96185dc92a40c98f6dbb8728743bRobert Swiecki            run->global->io.crashDir, arch_sigName(si.si_signo), pc, run->backtrace, si.si_code,
80682c707ccd07e9b6bb8eea2cea6d031a968fd33eaRobert Swiecki            sig_addr, instr, run->global->io.fileExtn);
8073bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    } else {
8083bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki        char localtmstr[PATH_MAX];
80981c6a0d2338d140606491be7ec82434b8a3eb316Robert Swiecki        util_getLocalTime("%F.%H:%M:%S", localtmstr, sizeof(localtmstr), time(NULL));
810e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        snprintf(run->crashFileName, sizeof(run->crashFileName),
8114e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki            "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%d.ADDR.%p.INSTR.%s.%s.%d.%s",
812ced3ebaa5a4a96185dc92a40c98f6dbb8728743bRobert Swiecki            run->global->io.crashDir, arch_sigName(si.si_signo), pc, run->backtrace, si.si_code,
81382c707ccd07e9b6bb8eea2cea6d031a968fd33eaRobert Swiecki            sig_addr, instr, localtmstr, pid, run->global->io.fileExtn);
8143bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
8153bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
816e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    if (files_exists(run->crashFileName)) {
817e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        LOG_I("It seems that '%s' already exists, skipping", run->crashFileName);
8181d74338219eefd3ff6dea33f488d1d0ddb360e04Jagger        // Clear filename so that verifier can understand we hit a duplicate
819e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        memset(run->crashFileName, 0, sizeof(run->crashFileName));
8201d74338219eefd3ff6dea33f488d1d0ddb360e04Jagger        return;
8211d74338219eefd3ff6dea33f488d1d0ddb360e04Jagger    }
822e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
823e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    if (files_writeBufToFile(run->crashFileName, run->dynamicFile, run->dynamicFileSz,
824d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC) == false) {
825e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        LOG_E("Couldn't copy '%s' to '%s'", run->fileName, run->crashFileName);
826e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        return;
8273bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
828ad6af2246b9d25e66266653ed292dc03928df7a5robert.swiecki@gmail.com
829e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    LOG_I("Ok, that's interesting, saved '%s' as '%s'", run->fileName, run->crashFileName);
8301d74338219eefd3ff6dea33f488d1d0ddb360e04Jagger
8312542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki    ATOMIC_POST_INC(run->global->cnts.uniqueCrashesCnt);
8321d74338219eefd3ff6dea33f488d1d0ddb360e04Jagger    /* If unique crash found, reset dynFile counter */
83378633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    ATOMIC_CLEAR(run->global->dynFileIterExpire);
8341d74338219eefd3ff6dea33f488d1d0ddb360e04Jagger
835e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    arch_traceGenerateReport(pid, run, funcs, funcCnt, &si, instr);
8363bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki}
8373bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
8389ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis/* TODO: Add report parsing support for other sanitizers too */
8390b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swieckistatic int arch_parseAsanReport(
840d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    run_t* run, pid_t pid, funcs_t* funcs, void** crashAddr, char** op) {
841d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    char crashReport[PATH_MAX] = {0};
8424e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    const char* const crashReportCpy = crashReport;
84382c707ccd07e9b6bb8eea2cea6d031a968fd33eaRobert Swiecki    snprintf(
84482c707ccd07e9b6bb8eea2cea6d031a968fd33eaRobert Swiecki        crashReport, sizeof(crashReport), "%s/%s.%d", run->global->io.workDir, kLOGPREFIX, pid);
845e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
8464e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    FILE* fReport = fopen(crashReport, "rb");
847e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    if (fReport == NULL) {
848c28e5ed675d22e7a209f96b4723b2d6571799f50Anestis Bechtsoudis        PLOG_D("Couldn't open '%s' - R/O mode", crashReport);
849e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        return -1;
850e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    }
8510b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { fclose(fReport); };
8520b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { unlink(crashReportCpy); };
853e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
854d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    char header[35] = {0};
855e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    snprintf(header, sizeof(header), "==%d==ERROR: AddressSanitizer:", pid);
856e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    size_t headerSz = strlen(header);
857e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    bool headerFound = false;
858e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
859e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    uint8_t frameIdx = 0;
860d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    char framePrefix[5] = {0};
861e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    snprintf(framePrefix, sizeof(framePrefix), "#%" PRIu8, frameIdx);
862e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
863e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    char *lineptr = NULL, *cAddr = NULL;
864e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    size_t n = 0;
8650b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { free(lineptr); };
866e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    for (;;) {
867e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        if (getline(&lineptr, &n, fReport) == -1) {
868e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            break;
869e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        }
870e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
871e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        /* First step is to identify header */
872e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        if (headerFound == false) {
873e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            if ((strlen(lineptr) > headerSz) && (strncmp(header, lineptr, headerSz) == 0)) {
874e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                headerFound = true;
875e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
876e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                /* Parse crash address */
877e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                cAddr = strstr(lineptr, "address 0x");
878e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                if (cAddr) {
879e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    cAddr = cAddr + strlen("address ");
8804e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                    char* endOff = strchr(cAddr, ' ');
881e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    cAddr[endOff - cAddr] = '\0';
8824e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                    *crashAddr = (void*)((size_t)strtoull(cAddr, NULL, 16));
883e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                } else {
884e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    *crashAddr = 0x0;
885e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                }
886e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
887e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            continue;
888e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        } else {
8894e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki            char* pLineLC = lineptr;
890e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            /* Trim leading spaces */
891ea0bcb6620729fdad8153681bc4e694b65c93b40Anestis Bechtsoudis            while (*pLineLC != '\0' && isspace(*pLineLC)) {
892ea0bcb6620729fdad8153681bc4e694b65c93b40Anestis Bechtsoudis                ++pLineLC;
893e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
894e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
8950ddd0787fa7ccc8af74fc5e2872a60b31557f862Anestis Bechtsoudis            /* End separator for crash thread stack trace is an empty line */
896ea0bcb6620729fdad8153681bc4e694b65c93b40Anestis Bechtsoudis            if ((*pLineLC == '\0') && (frameIdx != 0)) {
897e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                break;
898e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
899e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
900e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            /* Basic length checks */
901ea0bcb6620729fdad8153681bc4e694b65c93b40Anestis Bechtsoudis            if (strlen(pLineLC) < 10) {
902e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                continue;
903e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
904e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
905e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            /* If available parse the type of error (READ/WRITE) */
906ea0bcb6620729fdad8153681bc4e694b65c93b40Anestis Bechtsoudis            if (cAddr && strstr(pLineLC, cAddr)) {
907ca556e6076f3688d7a9730320230cabc4c714f9dAnestis Bechtsoudis                if (strncmp(pLineLC, "READ", 4) == 0) {
908e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    *op = "READ";
909ca556e6076f3688d7a9730320230cabc4c714f9dAnestis Bechtsoudis                } else if (strncmp(pLineLC, "WRITE", 5) == 0) {
910e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    *op = "WRITE";
911e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                }
912ca556e6076f3688d7a9730320230cabc4c714f9dAnestis Bechtsoudis                cAddr = NULL;
913e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
914e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
915e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            /* Check for crash thread frames */
916ea0bcb6620729fdad8153681bc4e694b65c93b40Anestis Bechtsoudis            if (strncmp(pLineLC, framePrefix, strlen(framePrefix)) == 0) {
917e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                /* Abort if max depth */
918e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                if (frameIdx >= _HF_MAX_FUNCS) {
919e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    break;
920e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                }
921e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
92223ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki                /*
923e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                 * Frames have following format:
924e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                 #0 0xaa860177  (/system/lib/libc.so+0x196177)
925e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                 */
9264e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                char* savePtr = NULL;
9276b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis                strtok_r(pLineLC, " ", &savePtr);
928d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                funcs[frameIdx].pc =
929d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                    (void*)((size_t)strtoull(strtok_r(NULL, " ", &savePtr), NULL, 16));
930e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
931e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                /* DSO & code offset parsing */
9324e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                char* targetStr = strtok_r(NULL, " ", &savePtr);
9334e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                char* startOff = strchr(targetStr, '(') + 1;
9344e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                char* plusOff = strchr(targetStr, '+');
9354e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                char* endOff = strrchr(targetStr, ')');
936e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                targetStr[endOff - startOff] = '\0';
937e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                if ((startOff == NULL) || (endOff == NULL) || (plusOff == NULL)) {
9386b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis                    LOG_D("Invalid ASan report entry (%s)", lineptr);
939e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                } else {
940d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                    size_t dsoSz =
941d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                        MIN(sizeof(funcs[frameIdx].mapName), (size_t)(plusOff - startOff));
942217836576aa0747bd53d2e4c1a59771135fb3903Anestis Bechtsoudis                    memcpy(funcs[frameIdx].mapName, startOff, dsoSz);
9434e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                    char* codeOff = targetStr + (plusOff - startOff) + 1;
944e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                    funcs[frameIdx].line = strtoull(codeOff, NULL, 16);
945e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                }
946e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
947e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                frameIdx++;
948e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis                snprintf(framePrefix, sizeof(framePrefix), "#%" PRIu8, frameIdx);
949e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
950e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        }
951e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    }
952e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
953e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    return frameIdx;
954e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis}
955e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
95639bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis/*
95739bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis * Special book keeping for cases where crashes are detected based on exitcode and not
958e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis * a raised signal. Such case is the ASan fuzzing for Android. Crash file name maintains
959e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis * the same format for compatibility with post campaign tools.
96039bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis */
961d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_traceExitSaveData(run_t* run, pid_t pid) {
962e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    REG_TYPE pc = 0;
9634e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    void* crashAddr = 0;
9644e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    char* op = "UNKNOWN";
96578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    pid_t targetPid = (run->global->linux.pid > 0) ? run->global->linux.pid : run->pid;
966e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
96739bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    /* Save only the first hit for each worker */
968e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    if (run->crashFileName[0] != '\0') {
96939bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis        return;
97039bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    }
971ac05480ed98bd630294ce1a43325eb12eb2354a5Anestis Bechtsoudis
97239bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    /* Increase global crashes counter */
9732542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki    ATOMIC_POST_INC(run->global->cnts.crashesCnt);
97478633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    ATOMIC_POST_AND(run->global->dynFileIterExpire, _HF_DYNFILE_SUB_MASK);
97577392728d91a8848fa9896dd7eea3d9690422417Anestis Bechtsoudis
9766b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis    /*
9776b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis     * If fuzzing with sanitizer coverage feedback increase crashes counter used
9786b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis     * as metric for dynFile evolution
9796b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis     */
98078633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->useSanCov) {
981e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        run->sanCovCnts.crashesCnt++;
9826b43204f9d4f96ac4e43cb323f8b1e4bb130d065Anestis Bechtsoudis    }
98339bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis
984e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    /* If sanitizer produces reports with stack traces (e.g. ASan), they're parsed manually */
985e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    int funcCnt = 0;
9864e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t));
9870b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { free(funcs); };
9886fb025e8c04bfec166ade14046458f124f3e344cAnestis Bechtsoudis    memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t));
989e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
9909ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    /* Sanitizers save reports against parent PID */
9919ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    if (targetPid != pid) {
9929ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis        return;
9939ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    }
99478633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    funcCnt = arch_parseAsanReport(run, pid, funcs, &crashAddr, &op);
995c209aa5de036693718d1ed0d9e775c3c92e5d424Anestis Bechtsoudis
9969ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    /*
9979ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis     * -1 error indicates a file not found for report. This is expected to happen often since
9989ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis     * ASan report is generated once for crashing TID. Ptrace arch is not guaranteed to parse
9999ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis     * that TID first. Not setting the 'crashFileName' variable will ensure that this branch
10009ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis     * is executed again for all TIDs until the matching report is found
10019ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis     */
10029ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    if (funcCnt == -1) {
10039ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis        return;
10049ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    }
10059ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis
10069ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    /* Since crash address is available, apply ignoreAddr filters */
100778633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (crashAddr < run->global->linux.ignoreAddr) {
1008e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        LOG_I("'%s' is interesting, but the crash addr is %p (below %p), skipping", run->fileName,
100978633d1b907775e7067fb04332859703de72ac3fRobert Swiecki            crashAddr, run->global->linux.ignoreAddr);
10109ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis        return;
10119ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    }
1012e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
10139ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    /* If frames successfully recovered, calculate stack hash & populate crash PC */
101478633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    arch_hashCallstack(run, funcs, funcCnt, false);
10154e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    pc = (uintptr_t)funcs[0].pc;
10169ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis
10179ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis    /*
101894afac6adfc35ef96bbede9fd8bcf0f2334a3dafAnestis Bechtsoudis     * Check if stackhash is blacklisted
10199ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis     */
1020d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    if (run->global->blacklist && (fastArray64Search(run->global->blacklist,
1021d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                                       run->global->blacklistCnt, run->backtrace) != -1)) {
1022e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", run->backtrace);
10232542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki        ATOMIC_POST_INC(run->global->cnts.blCrashesCnt);
102494afac6adfc35ef96bbede9fd8bcf0f2334a3dafAnestis Bechtsoudis        return;
1025e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    }
1026e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
102739bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    /* If dry run mode, copy file with same name into workspace */
102878633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->mutationsPerRun == 0U && run->global->useVerifier) {
1029ced3ebaa5a4a96185dc92a40c98f6dbb8728743bRobert Swiecki        snprintf(run->crashFileName, sizeof(run->crashFileName), "%s/%s", run->global->io.crashDir,
1030e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            run->origFileName);
103139bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    } else {
1032e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        /* Keep the crashes file name format identical */
103326fd6d58dfabe2d047d422c1098794980d59dad2Robert Swiecki        if (run->backtrace != 0ULL && run->global->io.saveUnique) {
1034e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            snprintf(run->crashFileName, sizeof(run->crashFileName),
10354e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%s.ADDR.%p.INSTR.%s.%s",
1036ced3ebaa5a4a96185dc92a40c98f6dbb8728743bRobert Swiecki                run->global->io.crashDir, "SAN", pc, run->backtrace, op, crashAddr, "[UNKNOWN]",
103782c707ccd07e9b6bb8eea2cea6d031a968fd33eaRobert Swiecki                run->global->io.fileExtn);
1038e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        } else {
1039e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            /* If no stack hash available, all crashes treated as unique */
1040e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            char localtmstr[PATH_MAX];
1041e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            util_getLocalTime("%F.%H:%M:%S", localtmstr, sizeof(localtmstr), time(NULL));
1042e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            snprintf(run->crashFileName, sizeof(run->crashFileName),
10434e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%s.ADDR.%p.INSTR.%s.%s.%s",
1044ced3ebaa5a4a96185dc92a40c98f6dbb8728743bRobert Swiecki                run->global->io.crashDir, "SAN", pc, run->backtrace, op, crashAddr, "[UNKNOWN]",
104582c707ccd07e9b6bb8eea2cea6d031a968fd33eaRobert Swiecki                localtmstr, run->global->io.fileExtn);
1046e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        }
104739bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    }
104839bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis
104939bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    bool dstFileExists = false;
1050e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    if (files_copyFile(run->fileName, run->crashFileName, &dstFileExists, true /* try_link */)) {
1051e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        LOG_I("Ok, that's interesting, saved '%s' as '%s'", run->fileName, run->crashFileName);
105239bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis
105339bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis        /* Increase unique crashes counters */
10542542dc097ea7f48c3bd3e250071687f29ee34e9fRobert Swiecki        ATOMIC_POST_INC(run->global->cnts.uniqueCrashesCnt);
105578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki        ATOMIC_CLEAR(run->global->dynFileIterExpire);
105639bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    } else {
1057e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        if (dstFileExists) {
1058e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            LOG_I("It seems that '%s' already exists, skipping", run->crashFileName);
1059e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
1060e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            /* Clear stack hash so that verifier can understand we hit a duplicate */
1061e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            run->backtrace = 0ULL;
1062e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        } else {
1063e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            LOG_E("Couldn't copy '%s' to '%s'", run->fileName, run->crashFileName);
1064e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
10650b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki            /* In case of write error, clear crashFileName to so that other monitored TIDs can retry
10660b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki             */
1067e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            memset(run->crashFileName, 0, sizeof(run->crashFileName));
1068e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        }
1069e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis
1070e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        /* Don't bother generating reports for duplicate or non-saved crashes */
107139bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis        return;
107239bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis    }
107339bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis
1074e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    /* Generate report */
1075e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    run->report[0] = '\0';
1076e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "EXIT_CODE: %s\n", HF_SAN_EXIT_CODE);
1077e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "ORIG_FNAME: %s\n", run->origFileName);
1078e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "FUZZ_FNAME: %s\n", run->crashFileName);
1079e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "PID: %d\n", pid);
1080e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "OPERATION: %s\n", op);
1081e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    util_ssnprintf(run->report, sizeof(run->report), "FAULT ADDRESS: %p\n", crashAddr);
1082e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    if (funcCnt > 0) {
1083e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        util_ssnprintf(run->report, sizeof(run->report), "STACK HASH: %016llx\n", run->backtrace);
1084e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki        util_ssnprintf(run->report, sizeof(run->report), "STACK:\n");
1085e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        for (int i = 0; i < funcCnt; i++) {
1086e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            util_ssnprintf(run->report, sizeof(run->report), " <" REG_PD REG_PM "> ",
10874e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki                (REG_TYPE)(long)funcs[i].pc);
1088217836576aa0747bd53d2e4c1a59771135fb3903Anestis Bechtsoudis            if (funcs[i].mapName[0] != '\0') {
1089e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki                util_ssnprintf(run->report, sizeof(run->report), "[%s + 0x%x]\n", funcs[i].mapName,
1090e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki                    funcs[i].line);
1091e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            } else {
1092e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki                util_ssnprintf(run->report, sizeof(run->report), "[]\n");
1093e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis            }
1094e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis        }
1095e5208106fe75cc37bc8655e67511d44731765051Anestis Bechtsoudis    }
109639bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis}
109739bf6cf7b6dea9ecaf0a2dbb126760582f4ba31fAnestis Bechtsoudis
1098d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_traceExitAnalyzeData(run_t* run, pid_t pid) {
10994e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    void* crashAddr = 0;
11004e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    char* op = "UNKNOWN";
110197633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis    int funcCnt = 0;
11024e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t));
11030b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { free(funcs); };
11046fb025e8c04bfec166ade14046458f124f3e344cAnestis Bechtsoudis    memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t));
110597633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis
110678633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    funcCnt = arch_parseAsanReport(run, pid, funcs, &crashAddr, &op);
110797633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis
110823ec02a25410945a30a76b7b6f53c6302de96e75Robert Swiecki    /*
110997633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis     * -1 error indicates a file not found for report. This is expected to happen often since
111097633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis     * ASan report is generated once for crashing TID. Ptrace arch is not guaranteed to parse
111197633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis     * that TID first. Not setting the 'crashFileName' variable will ensure that this branch
111297633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis     * is executed again for all TIDs until the matching report is found
111397633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis     */
111497633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis    if (funcCnt == -1) {
111597633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis        return;
111697633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis    }
111797633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis
111897633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis    /* If frames successfully recovered, calculate stack hash & populate crash PC */
111978633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    arch_hashCallstack(run, funcs, funcCnt, false);
112097633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis}
112197633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis
1122d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckivoid arch_traceExitAnalyze(run_t* run, pid_t pid) {
1123e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki    if (run->mainWorker) {
112497633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis        /* Main fuzzing threads */
112578633d1b907775e7067fb04332859703de72ac3fRobert Swiecki        arch_traceExitSaveData(run, pid);
112697633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis    } else {
112797633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis        /* Post crash analysis (e.g. crashes verifier) */
112878633d1b907775e7067fb04332859703de72ac3fRobert Swiecki        arch_traceExitAnalyzeData(run, pid);
112997633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis    }
113097633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis}
113197633ccbc54c47858efcedda15a038af0864bd16Anestis Bechtsoudis
1132a5a5c7b33295450a96682d71d4690d4c4343a006Jagger#define __WEVENT(status) ((status & 0xFF0000) >> 16)
1133d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic void arch_traceEvent(run_t* run, int status, pid_t pid) {
1134c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki    LOG_D("PID: %d, Ptrace event: %d", pid, __WEVENT(status));
1135dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    switch (__WEVENT(status)) {
1136d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki        case PTRACE_EVENT_EXIT: {
1137d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            unsigned long event_msg;
1138d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &event_msg) == -1) {
1139d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                PLOG_E("ptrace(PTRACE_GETEVENTMSG,%d) failed", pid);
1140d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                return;
1141d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            }
11425de55a2b8ecf248ad78f829008ac5c30519cbee2Jagger
1143d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            if (WIFEXITED(event_msg)) {
1144d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                LOG_D("PID: %d exited with exit_code: %lu", pid,
1145d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                    (unsigned long)WEXITSTATUS(event_msg));
1146d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                if (WEXITSTATUS(event_msg) == (unsigned long)HF_SAN_EXIT_CODE) {
1147d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                    arch_traceExitAnalyze(run, pid);
1148d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                }
1149d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            } else if (WIFSIGNALED(event_msg)) {
1150d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                LOG_D(
1151d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                    "PID: %d terminated with signal: %lu", pid, (unsigned long)WTERMSIG(event_msg));
1152d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            } else {
1153d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki                LOG_D("PID: %d exited with unknown status: %lu", pid, event_msg);
1154dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger            }
1155d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki        } break;
1156d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki        default:
1157d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki            break;
1158dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    }
1159dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger
1160a0df592ba4f3ed3c1c04efbe422caa9c380c7053Jagger    ptrace(PTRACE_CONT, pid, 0, 0);
1161a5a5c7b33295450a96682d71d4690d4c4343a006Jagger}
1162a5a5c7b33295450a96682d71d4690d4c4343a006Jagger
1163d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckivoid arch_traceAnalyze(run_t* run, int status, pid_t pid) {
11643bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    /*
1165a5a5c7b33295450a96682d71d4690d4c4343a006Jagger     * It's a ptrace event, deal with it elsewhere
11663bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     */
1167a5a5c7b33295450a96682d71d4690d4c4343a006Jagger    if (WIFSTOPPED(status) && __WEVENT(status)) {
116878633d1b907775e7067fb04332859703de72ac3fRobert Swiecki        return arch_traceEvent(run, status, pid);
11693bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
11703bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
1171a5a5c7b33295450a96682d71d4690d4c4343a006Jagger    if (WIFSTOPPED(status)) {
1172a5a5c7b33295450a96682d71d4690d4c4343a006Jagger        /*
1173a5a5c7b33295450a96682d71d4690d4c4343a006Jagger         * If it's an interesting signal, save the testcase
1174a5a5c7b33295450a96682d71d4690d4c4343a006Jagger         */
1175f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis        if (arch_sigs[WSTOPSIG(status)].important) {
11766b9e83de10dd9812eccfffb48ee1f56efcbd9c4aAnestis Bechtsoudis            /*
11776b9e83de10dd9812eccfffb48ee1f56efcbd9c4aAnestis Bechtsoudis             * If fuzzer worker is from core fuzzing process run full
11786b9e83de10dd9812eccfffb48ee1f56efcbd9c4aAnestis Bechtsoudis             * analysis. Otherwise just unwind and get stack hash signature.
11796b9e83de10dd9812eccfffb48ee1f56efcbd9c4aAnestis Bechtsoudis             */
1180e7294caf2461dcc9a7b666e8a62d516b8663206cRobert Swiecki            if (run->mainWorker) {
118178633d1b907775e7067fb04332859703de72ac3fRobert Swiecki                arch_traceSaveData(run, pid);
11826b9e83de10dd9812eccfffb48ee1f56efcbd9c4aAnestis Bechtsoudis            } else {
118378633d1b907775e7067fb04332859703de72ac3fRobert Swiecki                arch_traceAnalyzeData(run, pid);
11845c86ebc569dff1d715fc114de8ab308e9f4b89f3Anestis Bechtsoudis            }
1185a5a5c7b33295450a96682d71d4690d4c4343a006Jagger        }
1186cf03fc10df32d99d33266488bbcc6284b4d82652Robert Swiecki        /* Do not deliver SIGSTOP, as we don't support PTRACE_LISTEN anyway */
1187cf03fc10df32d99d33266488bbcc6284b4d82652Robert Swiecki        int sig = (WSTOPSIG(status) != SIGSTOP) ? WSTOPSIG(status) : 0;
1188cf03fc10df32d99d33266488bbcc6284b4d82652Robert Swiecki        ptrace(PTRACE_CONT, pid, 0, sig);
118922e66a9fc45532d2b663764a2d24abcec0561af7robert.swiecki@gmail.com        return;
11903bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
11913bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
11923bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    /*
11933bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     * Resumed by delivery of SIGCONT
11943bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     */
11953bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    if (WIFCONTINUED(status)) {
119622e66a9fc45532d2b663764a2d24abcec0561af7robert.swiecki@gmail.com        return;
11973bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
11983bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
11993bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    /*
1200124ba814038bb69717dff75455772fa301ee9e22robert.swiecki@gmail.com     * Process exited
12013bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki     */
1202dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    if (WIFEXITED(status)) {
12033e0ea96d416c371212f36237e183ddab874b0390Anestis Bechtsoudis        /*
12043e0ea96d416c371212f36237e183ddab874b0390Anestis Bechtsoudis         * Target exited with sanitizer defined exitcode (used when SIGABRT is not monitored)
12053e0ea96d416c371212f36237e183ddab874b0390Anestis Bechtsoudis         */
12069ea67cbd04e874ba33573f1dc01818cce8e887e8Anestis Bechtsoudis        if (WEXITSTATUS(status) == (unsigned long)HF_SAN_EXIT_CODE) {
120778633d1b907775e7067fb04332859703de72ac3fRobert Swiecki            arch_traceExitAnalyze(run, pid);
12083e0ea96d416c371212f36237e183ddab874b0390Anestis Bechtsoudis        }
1209dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger        return;
1210dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    }
1211dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger
1212dbc4a15c0efdad486d4cf928d6362307f7ca81b2Jagger    if (WIFSIGNALED(status)) {
121322e66a9fc45532d2b663764a2d24abcec0561af7robert.swiecki@gmail.com        return;
12143bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki    }
12153bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
12164e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    abort(); /* NOTREACHED */
12173bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki}
12183bb518cae7801e061cacd770b15d6d8982d94bcrobert.swiecki
1219d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckistatic bool arch_listThreads(int tasks[], size_t thrSz, int pid) {
12205f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    char path[512];
12215f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    snprintf(path, sizeof(path), "/proc/%d/task", pid);
12221bbe840db82a66ac115c2f5951e705a9549369d7Jagger
12231bbe840db82a66ac115c2f5951e705a9549369d7Jagger    /* An optimization, the number of threads is st.st_nlink - 2 (. and ..) */
12241bbe840db82a66ac115c2f5951e705a9549369d7Jagger    struct stat st;
12251bbe840db82a66ac115c2f5951e705a9549369d7Jagger    if (stat(path, &st) != -1) {
12261bbe840db82a66ac115c2f5951e705a9549369d7Jagger        if (st.st_nlink == 3) {
12271bbe840db82a66ac115c2f5951e705a9549369d7Jagger            tasks[0] = pid;
12281bbe840db82a66ac115c2f5951e705a9549369d7Jagger            tasks[1] = 0;
12291bbe840db82a66ac115c2f5951e705a9549369d7Jagger            return true;
12301bbe840db82a66ac115c2f5951e705a9549369d7Jagger        }
12311bbe840db82a66ac115c2f5951e705a9549369d7Jagger    }
12321bbe840db82a66ac115c2f5951e705a9549369d7Jagger
12331bbe840db82a66ac115c2f5951e705a9549369d7Jagger    size_t count = 0;
12344e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki    DIR* dir = opendir(path);
12355f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    if (!dir) {
1236c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        PLOG_E("Couldn't open dir '%s'", path);
12375f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        return false;
12385f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    }
12390b5661142ce282754e8c22e02ea8e9d66036ae58Robert Swiecki    defer { closedir(dir); };
12405f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com
12415f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    for (;;) {
1242acd1cdbed3f16f2186d00b799402c7fc9736bac6Robert Swiecki        errno = 0;
12434e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        struct dirent* res = readdir(dir);
1244acd1cdbed3f16f2186d00b799402c7fc9736bac6Robert Swiecki        if (res == NULL && errno != 0) {
1245c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki            PLOG_E("Couldn't read contents of '%s'", path);
12465f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com            return false;
12475f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        }
12485f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com
12495f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        if (res == NULL) {
12505f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com            break;
12515f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        }
12525f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com
12534e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki        pid_t pid = (pid_t)strtol(res->d_name, (char**)NULL, 10);
12545f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        if (pid == 0) {
1255c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki            LOG_D("The following dir entry couldn't be converted to pid_t '%s'", res->d_name);
12565f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com            continue;
12575f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        }
12585f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com
12595f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        tasks[count++] = pid;
1260c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_D("Added pid '%d' from '%s/%s'", pid, path, res->d_name);
12615f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com
12625f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        if (count >= thrSz) {
12635f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com            break;
12645f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        }
12655f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    }
1266c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki    PLOG_D("Total number of threads in pid '%d': '%zd'", pid, count);
12675f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    tasks[count + 1] = 0;
12685f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    if (count < 1) {
12695f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com        return false;
12705f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    }
12715f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    return true;
12725f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com}
12735f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com
1274d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckibool arch_traceWaitForPidStop(pid_t pid) {
12753aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger    for (;;) {
12763aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger        int status;
1277e79c47525e9b581c673a89913e330b409298bad2Jagger        pid_t ret = wait4(pid, &status, __WALL | WUNTRACED, NULL);
12783aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger        if (ret == -1 && errno == EINTR) {
12793aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger            continue;
12803aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger        }
12813aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger        if (ret == -1) {
128239cb9a724de1112cc3dea10ab9404808197c458cJagger            PLOG_W("wait4(pid=%d) failed", pid);
128339cb9a724de1112cc3dea10ab9404808197c458cJagger            return false;
12843aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger        }
128539cb9a724de1112cc3dea10ab9404808197c458cJagger        if (!WIFSTOPPED(status)) {
128639cb9a724de1112cc3dea10ab9404808197c458cJagger            LOG_W("PID %d not in a stopped state - status:%d", pid, status);
128739cb9a724de1112cc3dea10ab9404808197c458cJagger            return false;
1288d695262cfc0db52dbc79aa7f469cb3593784274bJagger        }
128939cb9a724de1112cc3dea10ab9404808197c458cJagger        return true;
12903aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger    }
12913aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger}
12923aacd58aca8931e6b54e4d2b684b3c283593afb8Jagger
12934f9d479548dad8529ac19d601e5df89efc17641bJagger#define MAX_THREAD_IN_TASK 4096
1294d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckibool arch_traceAttach(run_t* run, pid_t pid) {
129554adb764906a304c9a3a2e3f435fb54f754a3a7dRobert Swiecki/*
129654adb764906a304c9a3a2e3f435fb54f754a3a7dRobert Swiecki * It should be present since, at least, Linux kernel 3.8, but
129754adb764906a304c9a3a2e3f435fb54f754a3a7dRobert Swiecki * not always defined in kernel-headers
129854adb764906a304c9a3a2e3f435fb54f754a3a7dRobert Swiecki */
129954adb764906a304c9a3a2e3f435fb54f754a3a7dRobert Swiecki#if !defined(PTRACE_O_EXITKILL)
130054adb764906a304c9a3a2e3f435fb54f754a3a7dRobert Swiecki#define PTRACE_O_EXITKILL (1 << 20)
13014e595fb320d85cc29abe1cf38bea8eb04bfd301dRobert Swiecki#endif /* !defined(PTRACE_O_EXITKILL) */
1302746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki    long seize_options = PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK;
130378633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->linux.pid == 0) {
130420b0d0bb9627b335a88a74078efd389ace87f7c0Robert Swiecki        seize_options |= PTRACE_O_EXITKILL;
130520b0d0bb9627b335a88a74078efd389ace87f7c0Robert Swiecki    }
1306746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki    /* The event is only used with sanitizers */
130778633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->enableSanitizers) {
1308746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki        seize_options |= PTRACE_O_TRACEEXIT;
1309746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki    }
1310ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger
131178633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->linux.pid == 0 && arch_traceWaitForPidStop(pid) == false) {
13121c9d809c9dc2ed9d0983c5d87776fc250102675dRobert Swiecki        return false;
13131c9d809c9dc2ed9d0983c5d87776fc250102675dRobert Swiecki    }
13141c9d809c9dc2ed9d0983c5d87776fc250102675dRobert Swiecki
1315ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger    if (ptrace(PTRACE_SEIZE, pid, NULL, seize_options) == -1) {
131603a507ebde56b6a7a91fbbf24c7b4c936a833e4bJagger        PLOG_W("Couldn't ptrace(PTRACE_SEIZE) to pid: %d", pid);
1317ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger        return false;
1318ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger    }
131903a507ebde56b6a7a91fbbf24c7b4c936a833e4bJagger
13209402137bb77538503e6f0dc09f299103907dae2aJagger    LOG_D("Attached to PID: %d", pid);
1321ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger
1322746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki    /* It only makes sense to attach to threads with -p */
132378633d1b907775e7067fb04332859703de72ac3fRobert Swiecki    if (run->global->linux.pid == 0) {
1324746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki        return true;
1325746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki    }
1326746eaf040947790147b7ad5fc2875b33efe3b718Robert Swiecki
1327d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    int tasks[MAX_THREAD_IN_TASK + 1] = {0};
1328d526d31c9c86779f0d245cb950726a2142bcce8erobert.swiecki@gmail.com    if (!arch_listThreads(tasks, MAX_THREAD_IN_TASK, pid)) {
1329c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_E("Couldn't read thread list for pid '%d'", pid);
133028cba5cf23eb6edc5515bf320b10bb1286bb3df1robert.swiecki        return false;
133128cba5cf23eb6edc5515bf320b10bb1286bb3df1robert.swiecki    }
133228cba5cf23eb6edc5515bf320b10bb1286bb3df1robert.swiecki
13335f667521866d77bb5a0a76527b95046fdc98cbb7robert.swiecki@gmail.com    for (int i = 0; i < MAX_THREAD_IN_TASK && tasks[i]; i++) {
1334ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger        if (tasks[i] == pid) {
1335ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger            continue;
1336ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger        }
1337ea9595d37bfa5823532f275857a23cd9a814a6d7Jagger        if (ptrace(PTRACE_SEIZE, tasks[i], NULL, seize_options) == -1) {
133803a507ebde56b6a7a91fbbf24c7b4c936a833e4bJagger            PLOG_W("Couldn't ptrace(PTRACE_SEIZE) to pid: %d", tasks[i]);
1339c2bde39714e16e86d9a1259dab08f73cda269964Jagger            continue;
1340c2bde39714e16e86d9a1259dab08f73cda269964Jagger        }
13419402137bb77538503e6f0dc09f299103907dae2aJagger        LOG_D("Attached to PID: %d (thread_group:%d)", tasks[i], pid);
13427faf6f49114cdfb23d2e696961fa3ada807da78bJagger    }
134328cba5cf23eb6edc5515bf320b10bb1286bb3df1robert.swiecki    return true;
134428cba5cf23eb6edc5515bf320b10bb1286bb3df1robert.swiecki}
13454f9d479548dad8529ac19d601e5df89efc17641bJagger
1346d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckivoid arch_traceDetach(pid_t pid) {
13478b76934f112fdbca5cd6b902c1cc503a677bc47cRobert Swiecki    if (syscall(__NR_kill, pid, 0) == -1 && errno == ESRCH) {
1348c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_D("PID: %d no longer exists", pid);
1349ebc7479588bc8ae3f67a762ff0be1c7d01729e38Jagger        return;
1350ebc7479588bc8ae3f67a762ff0be1c7d01729e38Jagger    }
1351ebc7479588bc8ae3f67a762ff0be1c7d01729e38Jagger
1352d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swiecki    int tasks[MAX_THREAD_IN_TASK + 1] = {0};
13534f9d479548dad8529ac19d601e5df89efc17641bJagger    if (!arch_listThreads(tasks, MAX_THREAD_IN_TASK, pid)) {
1354c8c32dbf6444e4b7d27db38f40beb1bf904830b2Robert Swiecki        LOG_E("Couldn't read thread list for pid '%d'", pid);
13554f9d479548dad8529ac19d601e5df89efc17641bJagger        return;
13564f9d479548dad8529ac19d601e5df89efc17641bJagger    }
13574f9d479548dad8529ac19d601e5df89efc17641bJagger
13584f9d479548dad8529ac19d601e5df89efc17641bJagger    for (int i = 0; i < MAX_THREAD_IN_TASK && tasks[i]; i++) {
13594f9d479548dad8529ac19d601e5df89efc17641bJagger        ptrace(PTRACE_INTERRUPT, tasks[i], NULL, NULL);
1360019de49cb1a0901019839e0218174a0f7bf838e1Robert Swiecki        arch_traceWaitForPidStop(tasks[i]);
13614f9d479548dad8529ac19d601e5df89efc17641bJagger        ptrace(PTRACE_DETACH, tasks[i], NULL, NULL);
13624f9d479548dad8529ac19d601e5df89efc17641bJagger    }
13634f9d479548dad8529ac19d601e5df89efc17641bJagger}
1364f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis
1365d50ed4254e9260cd0b4ddb5f6608ec54447ec08dRobert Swieckivoid arch_traceSignalsInit(honggfuzz_t* hfuzz) {
1366f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis    /* Default is true for all platforms except Android */
1367f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis    arch_sigs[SIGABRT].important = hfuzz->monitorSIGABRT;
1368f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis
1369f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis    /* Default is false */
1370eba27171213942cb463e68f04ad2f2b70012d106Robert Swiecki    arch_sigs[SIGVTALRM].important = hfuzz->timing.tmoutVTALRM;
1371f1b6e89a45eb74ec2de816f82b682093421aa1e1Anestis Bechtsoudis}
1372