1/*
2 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7#include "ppapi/native_client/src/untrusted/pnacl_irt_shim/shim_ppapi.h"
8
9#include <string.h>
10#include "native_client/src/untrusted/irt/irt.h"
11#include "ppapi/nacl_irt/public/irt_ppapi.h"
12#include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h"
13#include "ppapi/native_client/src/untrusted/pnacl_irt_shim/irt_shim_ppapi.h"
14#include "ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.h"
15
16/* Use local strcmp to avoid dependency on libc. */
17static int mystrcmp(const char* s1, const char *s2) {
18  while((*s1 && *s2) && (*s1++ == *s2++));
19  return *(--s1) - *(--s2);
20}
21
22TYPE_nacl_irt_query __pnacl_real_irt_query_func = NULL;
23
24size_t __pnacl_wrap_irt_query_func(const char *interface_ident,
25                                     void *table, size_t tablesize) {
26  /*
27   * Note there is a benign race in initializing the wrapper.
28   * We build the "hook" structure by copying from the IRT's hook and then
29   * writing our wrapper for the ppapi method.  Two threads may end up
30   * attempting to do this simultaneously, which should not be a problem,
31   * as they are writing the same values.
32   */
33  if (0 != mystrcmp(interface_ident, NACL_IRT_PPAPIHOOK_v0_1)) {
34    /*
35     * The interface is not wrapped, so use the real interface.
36     */
37    return (*__pnacl_real_irt_query_func)(interface_ident, table, tablesize);
38  }
39#ifndef PNACL_SHIM_AOT
40  /*
41   * For PNaCl in-the-browser, redirect to using
42   * NACL_IRT_PPAPIHOOK_PNACL_PRIVATE_v0_1 instead of NACL_IRT_PPAPIHOOK_v0_1.
43   */
44  return (*__pnacl_real_irt_query_func)(NACL_IRT_PPAPIHOOK_PNACL_PRIVATE_v0_1,
45                                        table, tablesize);
46#else
47  /*
48   * For offline generated nexes, avoid depending on the private
49   * NACL_IRT_PPAPIHOOK_PNACL_PRIVATE_v0_1 interface, and just do the
50   * overriding here manually.
51   */
52  struct nacl_irt_ppapihook real_irt_ppapi_hook;
53  if ((*__pnacl_real_irt_query_func)(NACL_IRT_PPAPIHOOK_v0_1,
54                                     &real_irt_ppapi_hook,
55                                     sizeof real_irt_ppapi_hook) !=
56      sizeof real_irt_ppapi_hook) {
57    return 0;
58  }
59  real_irt_ppapi_start = real_irt_ppapi_hook.ppapi_start;
60  /*
61   * Copy the interface structure into the client.
62   */
63  struct nacl_irt_ppapihook *dest = table;
64  if (sizeof *dest <= tablesize) {
65    dest->ppapi_start = irt_shim_ppapi_start;
66    dest->ppapi_register_thread_creator =
67        real_irt_ppapi_hook.ppapi_register_thread_creator;
68    return sizeof *dest;
69  }
70  return 0;
71#endif
72}
73