Home | History | Annotate | Line # | Download | only in include
      1 /* plugin-api.h -- External linker plugin API.  */
      2 
      3 /* Copyright (C) 2009-2026 Free Software Foundation, Inc.
      4    Written by Cary Coutant <ccoutant (at) 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) */
    623