blob: b6cce8d2909b4bee3c252083ea8b3b2f6b24e26a [file] [log] [blame]
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070017#include <signal.h>
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070018
19#include "profile-extras.h"
20
21extern "C" {
22
Pirama Arumuga Nainar97f274e2021-01-15 15:27:59 -080023void __gcov_dump(void);
24void __gcov_reset(void);
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070025
Ray Essickb5d273d2020-01-09 11:51:27 -080026// storing SIG_ERR helps us detect (unlikely) looping.
27static sighandler_t chained_gcov_signal_handler = SIG_ERR;
28
29static void gcov_signal_handler(int signum) {
Pirama Arumuga Nainar97f274e2021-01-15 15:27:59 -080030 __gcov_dump();
31 __gcov_reset();
Ray Essickb5d273d2020-01-09 11:51:27 -080032 if (chained_gcov_signal_handler != SIG_ERR &&
33 chained_gcov_signal_handler != SIG_IGN &&
34 chained_gcov_signal_handler != SIG_DFL) {
35 (chained_gcov_signal_handler)(signum);
36 }
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070037}
38
Pirama Arumuga Nainare76c23d2019-06-03 10:56:35 -070039__attribute__((weak)) int init_profile_extras_once = 0;
40
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070041// Initialize libprofile-extras:
Oliver Nguyena0d4f062019-12-09 16:36:08 -080042// - Install a signal handler that triggers __gcov_flush on <COVERAGE_FLUSH_SIGNAL>.
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070043//
44// We want this initiazlier to run during load time.
45//
46// Just marking init_profile_extras() with __attribute__((constructor)) isn't
47// enough since the linker drops it from its output since no other symbol from
48// this static library is referenced.
49//
50// We force the linker to include init_profile_extras() by passing
51// '-uinit_profile_extras' to the linker (in build/soong).
52__attribute__((constructor)) int init_profile_extras(void) {
Pirama Arumuga Nainare76c23d2019-06-03 10:56:35 -070053 if (init_profile_extras_once)
54 return 0;
55 init_profile_extras_once = 1;
56
Ray Essickb5d273d2020-01-09 11:51:27 -080057 // is this instance already registered?
58 if (chained_gcov_signal_handler != SIG_ERR) {
59 return -1;
60 }
Oliver Nguyena0d4f062019-12-09 16:36:08 -080061 sighandler_t ret1 = signal(COVERAGE_FLUSH_SIGNAL, gcov_signal_handler);
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070062 if (ret1 == SIG_ERR) {
63 return -1;
64 }
Ray Essickb5d273d2020-01-09 11:51:27 -080065 chained_gcov_signal_handler = ret1;
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070066
Pirama Arumuga Nainar0d252222018-05-22 15:40:49 -070067 return 0;
68}
69}