10054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root/* 20054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * Copyright 2012, The Android Open Source Project 30054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * 40054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 50054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * you may not use this file except in compliance with the License. 60054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * You may obtain a copy of the License at 70054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * 80054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * http://www.apache.org/licenses/LICENSE-2.0 90054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * 100054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * Unless required by applicable law or agreed to in writing, software 110054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * distributed under the License is distributed on an "AS IS" BASIS, 120054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * See the License for the specific language governing permissions and 140054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root * limitations under the License. 150054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root */ 160054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 170054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) 180054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) 190054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CONCATENATE2(arg1, arg2) arg1##arg2 200054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 210054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define INTERRUPTER(sym) \ 220054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root if (real_##sym == NULL) \ 230054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root __init_##sym(); \ 240054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root if (maybe_interrupt()) { \ 250054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root errno = EINTR; \ 260054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root return -1; \ 270054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root } 280054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 290054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CALL_FUNCTION_1(sym, ret, type1) \ 300054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret (*real_##sym)(type1) = NULL; \ 310054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret sym(type1 arg1) { \ 320054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root INTERRUPTER(sym) \ 330054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root return real_##sym(arg1); \ 340054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root} 350054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 360054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CALL_FUNCTION_2(sym, ret, type1, type2) \ 370054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret (*real_##sym)(type1, type2) = NULL; \ 380054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret sym(type1 arg1, type2 arg2) { \ 390054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root INTERRUPTER(sym) \ 400054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root return real_##sym(arg1, arg2); \ 410054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root} 420054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 430054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CALL_FUNCTION_3(sym, ret, type1, type2, type3) \ 440054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret (*real_##sym)(type1, type2, type3) = NULL; \ 450054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret sym(type1 arg1, type2 arg2, type3 arg3) { \ 460054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root INTERRUPTER(sym) \ 470054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root return real_##sym(arg1, arg2, arg3); \ 480054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root} 490054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 500054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CALL_FUNCTION_4(sym, ret, type1, type2, type3, type4) \ 510054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret (*real_##sym)(type1, type2, type3, type4) = NULL; \ 520054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ 530054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root INTERRUPTER(sym) \ 540054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root return real_##sym(arg1, arg2, arg3, arg4); \ 550054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root} 560054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 570054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define CALL_FUNCTION_5(sym, ret, type1, type2, type3, type4, type5) \ 580054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret (*real_##sym)(type1, type2, type3, type4, type5) = NULL; \ 590054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ 600054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root INTERRUPTER(sym) \ 610054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root return real_##sym(arg1, arg2, arg3, arg4, arg5); \ 620054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root} 630054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 640054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define DEFINE_INTERCEPT_N(N, sym, ret, ...) \ 650054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootstatic void __init_##sym(void); \ 660054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny RootCONCATENATE(CALL_FUNCTION_, N)(sym, ret, __VA_ARGS__) \ 670054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Rootstatic void __init_##sym(void) { \ 680054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root real_##sym = dlsym(RTLD_NEXT, #sym); \ 690054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root if (real_##sym == NULL) { \ 700054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root fprintf(stderr, "Error hooking " #sym ": %s\n", dlerror()); \ 710054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root } \ 720054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root} 730054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 740054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define INTERCEPT_NARG(...) INTERCEPT_NARG_N(__VA_ARGS__, INTERCEPT_RSEQ_N()) 750054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define INTERCEPT_NARG_N(...) INTERCEPT_ARG_N(__VA_ARGS__) 760054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define INTERCEPT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N 770054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define INTERCEPT_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 780054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root 790054cbd4dbb9315419cc3c3b2aa1754a02fff1f4Kenny Root#define DEFINE_INTERCEPT(sym, ret, ...) DEFINE_INTERCEPT_N(INTERCEPT_NARG(__VA_ARGS__), sym, ret, __VA_ARGS__) 80