binutils (2.41)

(root)/
include/
plugin-api.h
       1  /* plugin-api.h -- External linker plugin API.  */
       2  
       3  /* Copyright (C) 2009-2023 Free Software Foundation, Inc.
       4     Written by Cary Coutant <ccoutant@google.com>.
       5  
       6     This file is part of binutils.
       7  
       8     This program is free software; you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation; either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     This program is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program; if not, write to the Free Software
      20     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      21     MA 02110-1301, USA.  */
      22  
      23  /* This file defines the interface for writing a linker plugin, which is
      24     described at < http://gcc.gnu.org/wiki/whopr/driver >.  */
      25  
      26  #ifndef PLUGIN_API_H
      27  #define PLUGIN_API_H
      28  
      29  #ifdef HAVE_STDINT_H
      30  #include <stdint.h>
      31  #elif defined(HAVE_INTTYPES_H)
      32  #include <inttypes.h>
      33  #endif
      34  #include <sys/types.h>
      35  #if !defined(HAVE_STDINT_H) && !defined(HAVE_INTTYPES_H) && \
      36      !defined(UINT64_MAX) && !defined(uint64_t)
      37  #error cannot find uint64_t type
      38  #endif
      39  
      40  /* Detect endianess based on gcc's (>=4.6.0) __BYTE_ORDER__ macro.  */
      41  #if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
      42      defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_PDP_ENDIAN__)
      43  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
      44  #define PLUGIN_LITTLE_ENDIAN 1
      45  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      46  #define PLUGIN_BIG_ENDIAN 1
      47  #elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
      48  #define PLUGIN_PDP_ENDIAN 1
      49  #endif
      50  
      51  #else
      52  /* Include header files to define endian macros.  */
      53  #if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__)
      54  #include <endian.h>
      55  
      56  #elif defined(__SVR4) && defined(__sun)
      57  #include <sys/byteorder.h>
      58  
      59  #elif defined(__FreeBSD__) || defined(__NetBSD__) || \
      60        defined(__DragonFly__) || defined(__minix)
      61  #include <sys/endian.h>
      62  
      63  #elif defined(__OpenBSD__)
      64  #include <machine/endian.h>
      65  #endif
      66  
      67  /* Detect endianess based on __BYTE_ORDER.  */
      68  #ifdef __BYTE_ORDER
      69  #if __BYTE_ORDER == __LITTLE_ENDIAN
      70  #define PLUGIN_LITTLE_ENDIAN 1
      71  #elif __BYTE_ORDER == __BIG_ENDIAN
      72  #define PLUGIN_BIG_ENDIAN 1
      73  #endif
      74  
      75  /* Detect endianess based on _BYTE_ORDER.  */
      76  #elif defined _BYTE_ORDER
      77  #if _BYTE_ORDER == _LITTLE_ENDIAN
      78  #define PLUGIN_LITTLE_ENDIAN 1
      79  #elif _BYTE_ORDER == _BIG_ENDIAN
      80  #define PLUGIN_BIG_ENDIAN 1
      81  #endif
      82  
      83  /* Detect based on _WIN32.  */
      84  #elif defined _WIN32
      85  #define PLUGIN_LITTLE_ENDIAN 1
      86  
      87  /* Detect based on __BIG_ENDIAN__ and __LITTLE_ENDIAN__ */
      88  #elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN
      89  #define PLUGIN_LITTLE_ENDIAN 1
      90  #elif defined __BIG_ENDIAN__ || defined _BIG_ENDIAN
      91  #define PLUGIN_BIG_ENDIAN 1
      92  #endif
      93  #endif
      94  
      95  #ifdef __cplusplus
      96  extern "C"
      97  {
      98  #endif
      99  
     100  /* Status code returned by most API routines.  */
     101  
     102  enum ld_plugin_status
     103  {
     104    LDPS_OK = 0,
     105    LDPS_NO_SYMS,         /* Attempt to get symbols that haven't been added. */
     106    LDPS_BAD_HANDLE,      /* No claimed object associated with given handle. */
     107    LDPS_ERR
     108    /* Additional Error codes TBD.  */
     109  };
     110  
     111  /* The version of the API specification.  */
     112  
     113  enum ld_plugin_api_version
     114  {
     115    LD_PLUGIN_API_VERSION = 1
     116  };
     117  
     118  /* The type of output file being generated by the linker.  */
     119  
     120  enum ld_plugin_output_file_type
     121  {
     122    LDPO_REL,
     123    LDPO_EXEC,
     124    LDPO_DYN,
     125    LDPO_PIE
     126  };
     127  
     128  /* An input file managed by the plugin library.  */
     129  
     130  struct ld_plugin_input_file
     131  {
     132    const char *name;
     133    int fd;
     134    off_t offset;
     135    off_t filesize;
     136    void *handle;
     137  };
     138  
     139  /* A symbol belonging to an input file managed by the plugin library.  */
     140  
     141  struct ld_plugin_symbol
     142  {
     143    char *name;
     144    char *version;
     145    /* This is for compatibility with older ABIs.  The older ABI defined
     146       only 'def' field.  */
     147  #if PLUGIN_BIG_ENDIAN == 1
     148    char unused;
     149    char section_kind;
     150    char symbol_type;
     151    char def;
     152  #elif PLUGIN_LITTLE_ENDIAN == 1
     153    char def;
     154    char symbol_type;
     155    char section_kind;
     156    char unused;
     157  #elif PLUGIN_PDP_ENDIAN == 1
     158    char symbol_type;
     159    char def;
     160    char unused;
     161    char section_kind;
     162  #else
     163  #error "Could not detect architecture endianess"
     164  #endif
     165    int visibility;
     166    uint64_t size;
     167    char *comdat_key;
     168    int resolution;
     169  };
     170  
     171  /* An object's section.  */
     172  
     173  struct ld_plugin_section
     174  {
     175    const void* handle;
     176    unsigned int shndx;
     177  };
     178  
     179  /* Whether the symbol is a definition, reference, or common, weak or not.  */
     180  
     181  enum ld_plugin_symbol_kind
     182  {
     183    LDPK_DEF,
     184    LDPK_WEAKDEF,
     185    LDPK_UNDEF,
     186    LDPK_WEAKUNDEF,
     187    LDPK_COMMON
     188  };
     189  
     190  /* The visibility of the symbol.  */
     191  
     192  enum ld_plugin_symbol_visibility
     193  {
     194    LDPV_DEFAULT,
     195    LDPV_PROTECTED,
     196    LDPV_INTERNAL,
     197    LDPV_HIDDEN
     198  };
     199  
     200  /* The type of the symbol.  */
     201  
     202  enum ld_plugin_symbol_type
     203  {
     204    LDST_UNKNOWN,
     205    LDST_FUNCTION,
     206    LDST_VARIABLE
     207  };
     208  
     209  enum ld_plugin_symbol_section_kind
     210  {
     211    LDSSK_DEFAULT,
     212    LDSSK_BSS
     213  };
     214  
     215  /* How a symbol is resolved.  */
     216  
     217  enum ld_plugin_symbol_resolution
     218  {
     219    LDPR_UNKNOWN = 0,
     220  
     221    /* Symbol is still undefined at this point.  */
     222    LDPR_UNDEF,
     223  
     224    /* This is the prevailing definition of the symbol, with references from
     225       regular object code.  */
     226    LDPR_PREVAILING_DEF,
     227  
     228    /* This is the prevailing definition of the symbol, with no
     229       references from regular objects.  It is only referenced from IR
     230       code.  */
     231    LDPR_PREVAILING_DEF_IRONLY,
     232  
     233    /* This definition was pre-empted by a definition in a regular
     234       object file.  */
     235    LDPR_PREEMPTED_REG,
     236  
     237    /* This definition was pre-empted by a definition in another IR file.  */
     238    LDPR_PREEMPTED_IR,
     239  
     240    /* This symbol was resolved by a definition in another IR file.  */
     241    LDPR_RESOLVED_IR,
     242  
     243    /* This symbol was resolved by a definition in a regular object
     244       linked into the main executable.  */
     245    LDPR_RESOLVED_EXEC,
     246  
     247    /* This symbol was resolved by a definition in a shared object.  */
     248    LDPR_RESOLVED_DYN,
     249  
     250    /* This is the prevailing definition of the symbol, with no
     251       references from regular objects.  It is only referenced from IR
     252       code, but the symbol is exported and may be referenced from
     253       a dynamic object (not seen at link time).  */
     254    LDPR_PREVAILING_DEF_IRONLY_EXP
     255  };
     256  
     257  /* The plugin library's "claim file" handler.  */
     258  
     259  typedef
     260  enum ld_plugin_status
     261  (*ld_plugin_claim_file_handler) (
     262    const struct ld_plugin_input_file *file, int *claimed);
     263  
     264  /* The plugin library's "claim file" handler, version 2.  */
     265  
     266  typedef
     267  enum ld_plugin_status
     268  (*ld_plugin_claim_file_handler_v2) (
     269    const struct ld_plugin_input_file *file, int *claimed, int known_used);
     270  
     271  /* The plugin library's "all symbols read" handler.  */
     272  
     273  typedef
     274  enum ld_plugin_status
     275  (*ld_plugin_all_symbols_read_handler) (void);
     276  
     277  /* The plugin library's cleanup handler.  */
     278  
     279  typedef
     280  enum ld_plugin_status
     281  (*ld_plugin_cleanup_handler) (void);
     282  
     283  /* The linker's interface for registering the "claim file" handler.  */
     284  
     285  typedef
     286  enum ld_plugin_status
     287  (*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler);
     288  
     289  /* The linker's interface for registering the "claim file" handler,
     290     version 2.  */
     291  
     292  typedef
     293  enum ld_plugin_status
     294  (*ld_plugin_register_claim_file_v2) (ld_plugin_claim_file_handler_v2 handler);
     295  
     296  /* The linker's interface for registering the "all symbols read" handler.  */
     297  
     298  typedef
     299  enum ld_plugin_status
     300  (*ld_plugin_register_all_symbols_read) (
     301    ld_plugin_all_symbols_read_handler handler);
     302  
     303  /* The linker's interface for registering the cleanup handler.  */
     304  
     305  typedef
     306  enum ld_plugin_status
     307  (*ld_plugin_register_cleanup) (ld_plugin_cleanup_handler handler);
     308  
     309  /* The linker's interface for adding symbols from a claimed input file.  */
     310  
     311  typedef
     312  enum ld_plugin_status
     313  (*ld_plugin_add_symbols) (void *handle, int nsyms,
     314                            const struct ld_plugin_symbol *syms);
     315  
     316  /* The linker's interface for getting the input file information with
     317     an open (possibly re-opened) file descriptor.  */
     318  
     319  typedef
     320  enum ld_plugin_status
     321  (*ld_plugin_get_input_file) (const void *handle,
     322                               struct ld_plugin_input_file *file);
     323  
     324  typedef
     325  enum ld_plugin_status
     326  (*ld_plugin_get_view) (const void *handle, const void **viewp);
     327  
     328  /* The linker's interface for releasing the input file.  */
     329  
     330  typedef
     331  enum ld_plugin_status
     332  (*ld_plugin_release_input_file) (const void *handle);
     333  
     334  /* The linker's interface for retrieving symbol resolution information.  */
     335  
     336  typedef
     337  enum ld_plugin_status
     338  (*ld_plugin_get_symbols) (const void *handle, int nsyms,
     339                            struct ld_plugin_symbol *syms);
     340  
     341  /* The linker's interface for adding a compiled input file.  */
     342  
     343  typedef
     344  enum ld_plugin_status
     345  (*ld_plugin_add_input_file) (const char *pathname);
     346  
     347  /* The linker's interface for adding a library that should be searched.  */
     348  
     349  typedef
     350  enum ld_plugin_status
     351  (*ld_plugin_add_input_library) (const char *libname);
     352  
     353  /* The linker's interface for adding a library path that should be searched.  */
     354  
     355  typedef
     356  enum ld_plugin_status
     357  (*ld_plugin_set_extra_library_path) (const char *path);
     358  
     359  /* The linker's interface for issuing a warning or error message.  */
     360  
     361  typedef
     362  enum ld_plugin_status
     363  (*ld_plugin_message) (int level, const char *format, ...);
     364  
     365  /* The linker's interface for retrieving the number of sections in an object.
     366     The handle is obtained in the claim_file handler.  This interface should
     367     only be invoked in the claim_file handler.   This function sets *COUNT to
     368     the number of sections in the object.  */
     369  
     370  typedef
     371  enum ld_plugin_status
     372  (*ld_plugin_get_input_section_count) (const void* handle, unsigned int *count);
     373  
     374  /* The linker's interface for retrieving the section type of a specific
     375     section in an object.  This interface should only be invoked in the
     376     claim_file handler.  This function sets *TYPE to an ELF SHT_xxx value.  */
     377  
     378  typedef
     379  enum ld_plugin_status
     380  (*ld_plugin_get_input_section_type) (const struct ld_plugin_section section,
     381                                       unsigned int *type);
     382  
     383  /* The linker's interface for retrieving the name of a specific section in
     384     an object. This interface should only be invoked in the claim_file handler.
     385     This function sets *SECTION_NAME_PTR to a null-terminated buffer allocated
     386     by malloc.  The plugin must free *SECTION_NAME_PTR.  */
     387  
     388  typedef
     389  enum ld_plugin_status
     390  (*ld_plugin_get_input_section_name) (const struct ld_plugin_section section,
     391                                       char **section_name_ptr);
     392  
     393  /* The linker's interface for retrieving the contents of a specific section
     394     in an object.  This interface should only be invoked in the claim_file
     395     handler.  This function sets *SECTION_CONTENTS to point to a buffer that is
     396     valid until clam_file handler returns.  It sets *LEN to the size of the
     397     buffer.  */
     398  
     399  typedef
     400  enum ld_plugin_status
     401  (*ld_plugin_get_input_section_contents) (const struct ld_plugin_section section,
     402                                           const unsigned char **section_contents,
     403                                           size_t* len);
     404  
     405  /* The linker's interface for specifying the desired order of sections.
     406     The sections should be specifed using the array SECTION_LIST in the
     407     order in which they should appear in the final layout.  NUM_SECTIONS
     408     specifies the number of entries in each array.  This should be invoked
     409     in the all_symbols_read handler.  */
     410  
     411  typedef
     412  enum ld_plugin_status
     413  (*ld_plugin_update_section_order) (const struct ld_plugin_section *section_list,
     414  				   unsigned int num_sections);
     415  
     416  /* The linker's interface for specifying that reordering of sections is
     417     desired so that the linker can prepare for it.  This should be invoked
     418     before update_section_order, preferably in the claim_file handler.  */
     419  
     420  typedef
     421  enum ld_plugin_status
     422  (*ld_plugin_allow_section_ordering) (void);
     423  
     424  /* The linker's interface for specifying that a subset of sections is
     425     to be mapped to a unique segment.  If the plugin wants to call
     426     unique_segment_for_sections, it must call this function from a
     427     claim_file_handler or when it is first loaded.  */
     428  
     429  typedef
     430  enum ld_plugin_status
     431  (*ld_plugin_allow_unique_segment_for_sections) (void);
     432  
     433  /* The linker's interface for specifying that a specific set of sections
     434     must be mapped to a unique segment.  ELF segments do not have names
     435     and the NAME is used as the name of the newly created output section
     436     that is then placed in the unique PT_LOAD segment.  FLAGS is used to
     437     specify if any additional segment flags need to be set.  For instance,
     438     a specific segment flag can be set to identify this segment.  Unsetting
     439     segment flags that would be set by default is not possible.  The
     440     parameter SEGMENT_ALIGNMENT when non-zero will override the default.  */
     441  
     442  typedef
     443  enum ld_plugin_status
     444  (*ld_plugin_unique_segment_for_sections) (
     445      const char* segment_name,
     446      uint64_t segment_flags,
     447      uint64_t segment_alignment,
     448      const struct ld_plugin_section * section_list,
     449      unsigned int num_sections);
     450  
     451  /* The linker's interface for retrieving the section alignment requirement
     452     of a specific section in an object.  This interface should only be invoked in the
     453     claim_file handler.  This function sets *ADDRALIGN to the ELF sh_addralign
     454     value of the input section.  */
     455  
     456  typedef
     457  enum ld_plugin_status
     458  (*ld_plugin_get_input_section_alignment) (const struct ld_plugin_section section,
     459                                            unsigned int *addralign);
     460  
     461  /* The linker's interface for retrieving the section size of a specific section
     462     in an object.  This interface should only be invoked in the claim_file handler.
     463     This function sets *SECSIZE to the ELF sh_size
     464     value of the input section.  */
     465  
     466  typedef
     467  enum ld_plugin_status
     468  (*ld_plugin_get_input_section_size) (const struct ld_plugin_section section,
     469                                       uint64_t *secsize);
     470  
     471  typedef
     472  enum ld_plugin_status
     473  (*ld_plugin_new_input_handler) (const struct ld_plugin_input_file *file);
     474  
     475  /* The linker's interface for registering the "new_input" handler. This handler
     476     will be notified when a new input file has been added after the
     477     all_symbols_read event, allowing the plugin to, for example, set a unique
     478     segment for sections in plugin-generated input files. */
     479  
     480  typedef
     481  enum ld_plugin_status
     482  (*ld_plugin_register_new_input) (ld_plugin_new_input_handler handler);
     483  
     484  /* The linker's interface for getting the list of wrapped symbols using the
     485     --wrap option. This sets *NUM_SYMBOLS to number of wrapped symbols and
     486     *WRAP_SYMBOL_LIST to the list of wrapped symbols. */
     487  
     488  typedef
     489  enum ld_plugin_status
     490  (*ld_plugin_get_wrap_symbols) (uint64_t *num_symbols,
     491                                 const char ***wrap_symbol_list);
     492  
     493  enum ld_plugin_level
     494  {
     495    LDPL_INFO,
     496    LDPL_WARNING,
     497    LDPL_ERROR,
     498    LDPL_FATAL
     499  };
     500  
     501  /* Contract between a plug-in and a linker.  */
     502  
     503  enum linker_api_version
     504  {
     505     /* The linker/plugin do not implement any of the API levels below, the API
     506         is determined solely via the transfer vector.  */
     507     LAPI_V0,
     508  
     509     /* API level v1.  The linker provides get_symbols_v3, add_symbols_v2,
     510        the plugin will use that and not any lower versions.
     511        claim_file is thread-safe on the plugin side and
     512        add_symbols on the linker side.  */
     513     LAPI_V1
     514  };
     515  
     516  /* The linker's interface for API version negotiation.  A plug-in calls
     517    the function (with its IDENTIFIER and VERSION), plus minimal and maximal
     518    version of linker_api_version is provided.  Linker then returns selected
     519    API version and provides its IDENTIFIER and VERSION.  The returned value
     520    by linker must be in range [MINIMAL_API_SUPPORTED, MAXIMAL_API_SUPPORTED].
     521    Identifier pointers remain valid as long as the plugin is loaded.  */
     522  
     523  typedef
     524  int
     525  (*ld_plugin_get_api_version) (const char *plugin_identifier,
     526  			      const char *plugin_version,
     527  			      int minimal_api_supported,
     528  			      int maximal_api_supported,
     529  			      const char **linker_identifier,
     530  			      const char **linker_version);
     531  
     532  /* Values for the tv_tag field of the transfer vector.  */
     533  
     534  enum ld_plugin_tag
     535  {
     536    LDPT_NULL,
     537    LDPT_API_VERSION,
     538    LDPT_GOLD_VERSION,
     539    LDPT_LINKER_OUTPUT,
     540    LDPT_OPTION,
     541    LDPT_REGISTER_CLAIM_FILE_HOOK,
     542    LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
     543    LDPT_REGISTER_CLEANUP_HOOK,
     544    LDPT_ADD_SYMBOLS,
     545    LDPT_GET_SYMBOLS,
     546    LDPT_ADD_INPUT_FILE,
     547    LDPT_MESSAGE,
     548    LDPT_GET_INPUT_FILE,
     549    LDPT_RELEASE_INPUT_FILE,
     550    LDPT_ADD_INPUT_LIBRARY,
     551    LDPT_OUTPUT_NAME,
     552    LDPT_SET_EXTRA_LIBRARY_PATH,
     553    LDPT_GNU_LD_VERSION,
     554    LDPT_GET_VIEW,
     555    LDPT_GET_INPUT_SECTION_COUNT,
     556    LDPT_GET_INPUT_SECTION_TYPE,
     557    LDPT_GET_INPUT_SECTION_NAME,
     558    LDPT_GET_INPUT_SECTION_CONTENTS,
     559    LDPT_UPDATE_SECTION_ORDER,
     560    LDPT_ALLOW_SECTION_ORDERING,
     561    LDPT_GET_SYMBOLS_V2,
     562    LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS,
     563    LDPT_UNIQUE_SEGMENT_FOR_SECTIONS,
     564    LDPT_GET_SYMBOLS_V3,
     565    LDPT_GET_INPUT_SECTION_ALIGNMENT,
     566    LDPT_GET_INPUT_SECTION_SIZE,
     567    LDPT_REGISTER_NEW_INPUT_HOOK,
     568    LDPT_GET_WRAP_SYMBOLS,
     569    LDPT_ADD_SYMBOLS_V2,
     570    LDPT_GET_API_VERSION,
     571    LDPT_REGISTER_CLAIM_FILE_HOOK_V2
     572  };
     573  
     574  /* The plugin transfer vector.  */
     575  
     576  struct ld_plugin_tv
     577  {
     578    enum ld_plugin_tag tv_tag;
     579    union
     580    {
     581      int tv_val;
     582      const char *tv_string;
     583      ld_plugin_register_claim_file tv_register_claim_file;
     584      ld_plugin_register_claim_file_v2 tv_register_claim_file_v2;
     585      ld_plugin_register_all_symbols_read tv_register_all_symbols_read;
     586      ld_plugin_register_cleanup tv_register_cleanup;
     587      ld_plugin_add_symbols tv_add_symbols;
     588      ld_plugin_get_symbols tv_get_symbols;
     589      ld_plugin_add_input_file tv_add_input_file;
     590      ld_plugin_message tv_message;
     591      ld_plugin_get_input_file tv_get_input_file;
     592      ld_plugin_get_view tv_get_view;
     593      ld_plugin_release_input_file tv_release_input_file;
     594      ld_plugin_add_input_library tv_add_input_library;
     595      ld_plugin_set_extra_library_path tv_set_extra_library_path;
     596      ld_plugin_get_input_section_count tv_get_input_section_count;
     597      ld_plugin_get_input_section_type tv_get_input_section_type;
     598      ld_plugin_get_input_section_name tv_get_input_section_name;
     599      ld_plugin_get_input_section_contents tv_get_input_section_contents;
     600      ld_plugin_update_section_order tv_update_section_order;
     601      ld_plugin_allow_section_ordering tv_allow_section_ordering;
     602      ld_plugin_allow_unique_segment_for_sections tv_allow_unique_segment_for_sections; 
     603      ld_plugin_unique_segment_for_sections tv_unique_segment_for_sections;
     604      ld_plugin_get_input_section_alignment tv_get_input_section_alignment;
     605      ld_plugin_get_input_section_size tv_get_input_section_size;
     606      ld_plugin_register_new_input tv_register_new_input;
     607      ld_plugin_get_wrap_symbols tv_get_wrap_symbols;
     608      ld_plugin_get_api_version tv_get_api_version;
     609    } tv_u;
     610  };
     611  
     612  /* The plugin library's "onload" entry point.  */
     613  
     614  typedef
     615  enum ld_plugin_status
     616  (*ld_plugin_onload) (struct ld_plugin_tv *tv);
     617  
     618  #ifdef __cplusplus
     619  }
     620  #endif
     621  
     622  #endif /* !defined(PLUGIN_API_H) */