ruby-oci8 2.1.7 → 2.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +136 -0
 - data/NEWS +61 -0
 - data/README.md +2 -2
 - data/VERSION +1 -1
 - data/dist-files +5 -0
 - data/docs/install-instant-client.md +2 -0
 - data/ext/oci8/attr.c +0 -9
 - data/ext/oci8/bind.c +86 -28
 - data/ext/oci8/connection_pool.c +32 -17
 - data/ext/oci8/extconf.rb +21 -0
 - data/ext/oci8/hook_funcs.c +215 -0
 - data/ext/oci8/lob.c +363 -168
 - data/ext/oci8/metadata.c +43 -26
 - data/ext/oci8/object.c +115 -36
 - data/ext/oci8/oci8.c +392 -269
 - data/ext/oci8/oci8.h +88 -33
 - data/ext/oci8/oci8lib.c +59 -28
 - data/ext/oci8/ocidatetime.c +100 -36
 - data/ext/oci8/ocihandle.c +288 -286
 - data/ext/oci8/ocinumber.c +172 -112
 - data/ext/oci8/oradate.c +129 -87
 - data/ext/oci8/plthook.h +56 -0
 - data/ext/oci8/plthook_elf.c +537 -0
 - data/ext/oci8/plthook_osx.c +474 -0
 - data/ext/oci8/plthook_win32.c +376 -0
 - data/ext/oci8/stmt.c +112 -75
 - data/lib/oci8/cursor.rb +1 -1
 - data/lib/oci8/oci8.rb +71 -0
 - data/lib/oci8/properties.rb +18 -3
 - metadata +10 -16
 
| 
         @@ -0,0 +1,474 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /* -*- indent-tabs-mode: nil -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
             *
         
     | 
| 
      
 3 
     | 
    
         
            +
             * plthook_osx.c -- implemention of plthook for OS X
         
     | 
| 
      
 4 
     | 
    
         
            +
             *
         
     | 
| 
      
 5 
     | 
    
         
            +
             * URL: https://github.com/kubo/plthook
         
     | 
| 
      
 6 
     | 
    
         
            +
             *
         
     | 
| 
      
 7 
     | 
    
         
            +
             * ------------------------------------------------------
         
     | 
| 
      
 8 
     | 
    
         
            +
             *
         
     | 
| 
      
 9 
     | 
    
         
            +
             * Copyright 2014 Kubo Takehiro <kubo@jiubao.org>
         
     | 
| 
      
 10 
     | 
    
         
            +
             *
         
     | 
| 
      
 11 
     | 
    
         
            +
             * Redistribution and use in source and binary forms, with or without modification, are
         
     | 
| 
      
 12 
     | 
    
         
            +
             * permitted provided that the following conditions are met:
         
     | 
| 
      
 13 
     | 
    
         
            +
             *
         
     | 
| 
      
 14 
     | 
    
         
            +
             *    1. Redistributions of source code must retain the above copyright notice, this list of
         
     | 
| 
      
 15 
     | 
    
         
            +
             *       conditions and the following disclaimer.
         
     | 
| 
      
 16 
     | 
    
         
            +
             *
         
     | 
| 
      
 17 
     | 
    
         
            +
             *    2. Redistributions in binary form must reproduce the above copyright notice, this list
         
     | 
| 
      
 18 
     | 
    
         
            +
             *       of conditions and the following disclaimer in the documentation and/or other materials
         
     | 
| 
      
 19 
     | 
    
         
            +
             *       provided with the distribution.
         
     | 
| 
      
 20 
     | 
    
         
            +
             *
         
     | 
| 
      
 21 
     | 
    
         
            +
             * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED
         
     | 
| 
      
 22 
     | 
    
         
            +
             * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
         
     | 
| 
      
 23 
     | 
    
         
            +
             * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
         
     | 
| 
      
 24 
     | 
    
         
            +
             * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
         
     | 
| 
      
 25 
     | 
    
         
            +
             * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         
     | 
| 
      
 26 
     | 
    
         
            +
             * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
         
     | 
| 
      
 27 
     | 
    
         
            +
             * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
         
     | 
| 
      
 28 
     | 
    
         
            +
             * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
         
     | 
| 
      
 29 
     | 
    
         
            +
             * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         
     | 
| 
      
 30 
     | 
    
         
            +
             *
         
     | 
| 
      
 31 
     | 
    
         
            +
             * The views and conclusions contained in the software and documentation are those of the
         
     | 
| 
      
 32 
     | 
    
         
            +
             * authors and should not be interpreted as representing official policies, either expressed
         
     | 
| 
      
 33 
     | 
    
         
            +
             * or implied, of the authors.
         
     | 
| 
      
 34 
     | 
    
         
            +
             *
         
     | 
| 
      
 35 
     | 
    
         
            +
             */
         
     | 
| 
      
 36 
     | 
    
         
            +
            #include <stdio.h>
         
     | 
| 
      
 37 
     | 
    
         
            +
            #include <stdarg.h>
         
     | 
| 
      
 38 
     | 
    
         
            +
            #include <stdlib.h>
         
     | 
| 
      
 39 
     | 
    
         
            +
            #include <string.h>
         
     | 
| 
      
 40 
     | 
    
         
            +
            #include <dlfcn.h>
         
     | 
| 
      
 41 
     | 
    
         
            +
            #include <mach-o/dyld.h>
         
     | 
| 
      
 42 
     | 
    
         
            +
            #include "plthook.h"
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            // #define PLTHOOK_DEBUG_CMD 1
         
     | 
| 
      
 45 
     | 
    
         
            +
            // #define PLTHOOK_DEBUG_BIND 1
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            #ifdef PLTHOOK_DEBUG_CMD
         
     | 
| 
      
 48 
     | 
    
         
            +
            #define DEBUG_CMD(...) fprintf(stderr, __VA_ARGS__)
         
     | 
| 
      
 49 
     | 
    
         
            +
            #else
         
     | 
| 
      
 50 
     | 
    
         
            +
            #define DEBUG_CMD(...)
         
     | 
| 
      
 51 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            #ifdef PLTHOOK_DEBUG_BIND
         
     | 
| 
      
 54 
     | 
    
         
            +
            #define DEBUG_BIND(...) fprintf(stderr, __VA_ARGS__)
         
     | 
| 
      
 55 
     | 
    
         
            +
            #else
         
     | 
| 
      
 56 
     | 
    
         
            +
            #define DEBUG_BIND(...)
         
     | 
| 
      
 57 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            #ifdef __LP64__
         
     | 
| 
      
 60 
     | 
    
         
            +
            #define segment_command_ segment_command_64
         
     | 
| 
      
 61 
     | 
    
         
            +
            #else
         
     | 
| 
      
 62 
     | 
    
         
            +
            #define segment_command_ segment_command
         
     | 
| 
      
 63 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
            typedef struct {
         
     | 
| 
      
 66 
     | 
    
         
            +
                const char *name;
         
     | 
| 
      
 67 
     | 
    
         
            +
                void **addr;
         
     | 
| 
      
 68 
     | 
    
         
            +
            } bind_address_t;
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            struct plthook {
         
     | 
| 
      
 71 
     | 
    
         
            +
                unsigned int num_entries;
         
     | 
| 
      
 72 
     | 
    
         
            +
                bind_address_t entries[1];
         
     | 
| 
      
 73 
     | 
    
         
            +
            };
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *mh);
         
     | 
| 
      
 76 
     | 
    
         
            +
            static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint32_t lazy_bind_off, uint32_t lazy_bind_size, struct segment_command_ **segments, int addrdiff);
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
         
     | 
| 
      
 79 
     | 
    
         
            +
            static void set_bind_addr(unsigned int *idx, plthook_t *plthook, const uint8_t *base, const char *sym_name, int seg_index, int seg_offset, struct segment_command_ **segments);
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            static uint64_t uleb128(const uint8_t **p)
         
     | 
| 
      
 82 
     | 
    
         
            +
            {
         
     | 
| 
      
 83 
     | 
    
         
            +
                uint64_t r = 0;
         
     | 
| 
      
 84 
     | 
    
         
            +
                int s = 0;
         
     | 
| 
      
 85 
     | 
    
         
            +
                do {
         
     | 
| 
      
 86 
     | 
    
         
            +
                    r |= (uint64_t)(**p & 0x7f) << s;
         
     | 
| 
      
 87 
     | 
    
         
            +
                    s += 7;
         
     | 
| 
      
 88 
     | 
    
         
            +
                } while (*(*p)++ >= 0x80);
         
     | 
| 
      
 89 
     | 
    
         
            +
                return r;
         
     | 
| 
      
 90 
     | 
    
         
            +
            }
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            static int64_t sleb128(const uint8_t** p)
         
     | 
| 
      
 93 
     | 
    
         
            +
            {
         
     | 
| 
      
 94 
     | 
    
         
            +
                int64_t r = 0;
         
     | 
| 
      
 95 
     | 
    
         
            +
                int s = 0;
         
     | 
| 
      
 96 
     | 
    
         
            +
                for (;;) {
         
     | 
| 
      
 97 
     | 
    
         
            +
                    uint8_t b = *(*p)++;
         
     | 
| 
      
 98 
     | 
    
         
            +
                    if (b < 0x80) {
         
     | 
| 
      
 99 
     | 
    
         
            +
                      if (b & 0x40) {
         
     | 
| 
      
 100 
     | 
    
         
            +
                        r -= (0x80 - b) << s;
         
     | 
| 
      
 101 
     | 
    
         
            +
                      } else {
         
     | 
| 
      
 102 
     | 
    
         
            +
                        r |= (b & 0x3f) << s;
         
     | 
| 
      
 103 
     | 
    
         
            +
                      }
         
     | 
| 
      
 104 
     | 
    
         
            +
                      break;
         
     | 
| 
      
 105 
     | 
    
         
            +
                    }
         
     | 
| 
      
 106 
     | 
    
         
            +
                    r |= (b & 0x7f) << s;
         
     | 
| 
      
 107 
     | 
    
         
            +
                    s += 7;
         
     | 
| 
      
 108 
     | 
    
         
            +
                }
         
     | 
| 
      
 109 
     | 
    
         
            +
                return r;
         
     | 
| 
      
 110 
     | 
    
         
            +
            }
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            static char errmsg[512];
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            int plthook_open(plthook_t **plthook_out, const char *filename)
         
     | 
| 
      
 115 
     | 
    
         
            +
            {
         
     | 
| 
      
 116 
     | 
    
         
            +
                uint32_t idx = 0;
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                if (filename != NULL) {
         
     | 
| 
      
 119 
     | 
    
         
            +
                    size_t namelen = strlen(filename);
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                    while (1) {
         
     | 
| 
      
 122 
     | 
    
         
            +
                        const char *image_name = _dyld_get_image_name(idx);
         
     | 
| 
      
 123 
     | 
    
         
            +
                        size_t offset = 0;
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                        if (image_name == NULL) {
         
     | 
| 
      
 126 
     | 
    
         
            +
                            *plthook_out = NULL;
         
     | 
| 
      
 127 
     | 
    
         
            +
                            set_errmsg("Cannot find file: %s", filename);
         
     | 
| 
      
 128 
     | 
    
         
            +
                            return PLTHOOK_FILE_NOT_FOUND;
         
     | 
| 
      
 129 
     | 
    
         
            +
                        }
         
     | 
| 
      
 130 
     | 
    
         
            +
                        if (*filename != '/') {
         
     | 
| 
      
 131 
     | 
    
         
            +
                            size_t image_name_len = strlen(image_name);
         
     | 
| 
      
 132 
     | 
    
         
            +
                            if (image_name_len > namelen) {
         
     | 
| 
      
 133 
     | 
    
         
            +
                                offset = image_name_len - namelen;
         
     | 
| 
      
 134 
     | 
    
         
            +
                            }
         
     | 
| 
      
 135 
     | 
    
         
            +
                        }
         
     | 
| 
      
 136 
     | 
    
         
            +
                        if (strcmp(image_name + offset, filename) == 0) {
         
     | 
| 
      
 137 
     | 
    
         
            +
                            break;
         
     | 
| 
      
 138 
     | 
    
         
            +
                        }
         
     | 
| 
      
 139 
     | 
    
         
            +
                        idx++;
         
     | 
| 
      
 140 
     | 
    
         
            +
                    }
         
     | 
| 
      
 141 
     | 
    
         
            +
                }
         
     | 
| 
      
 142 
     | 
    
         
            +
                return plthook_open_real(plthook_out, _dyld_get_image_header(idx));
         
     | 
| 
      
 143 
     | 
    
         
            +
            }
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
            int plthook_open_by_address(plthook_t **plthook_out, void *address)
         
     | 
| 
      
 146 
     | 
    
         
            +
            {
         
     | 
| 
      
 147 
     | 
    
         
            +
                Dl_info dlinfo;
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                if (!dladdr(address, &dlinfo)) {
         
     | 
| 
      
 150 
     | 
    
         
            +
                    *plthook_out = NULL;
         
     | 
| 
      
 151 
     | 
    
         
            +
                    set_errmsg("Cannot find address: %p", address);
         
     | 
| 
      
 152 
     | 
    
         
            +
                    return PLTHOOK_FILE_NOT_FOUND;
         
     | 
| 
      
 153 
     | 
    
         
            +
                }
         
     | 
| 
      
 154 
     | 
    
         
            +
                return plthook_open_real(plthook_out, dlinfo.dli_fbase);
         
     | 
| 
      
 155 
     | 
    
         
            +
            }
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
            #define NUM_SEGMENTS 10
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
            static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *mh)
         
     | 
| 
      
 160 
     | 
    
         
            +
            {
         
     | 
| 
      
 161 
     | 
    
         
            +
                struct load_command *cmd;
         
     | 
| 
      
 162 
     | 
    
         
            +
                const uint8_t *base = (const uint8_t *)mh;
         
     | 
| 
      
 163 
     | 
    
         
            +
                uint32_t lazy_bind_off = 0;
         
     | 
| 
      
 164 
     | 
    
         
            +
                uint32_t lazy_bind_size = 0;
         
     | 
| 
      
 165 
     | 
    
         
            +
                struct segment_command_ *segments[NUM_SEGMENTS];
         
     | 
| 
      
 166 
     | 
    
         
            +
                int segment_idx = 0;
         
     | 
| 
      
 167 
     | 
    
         
            +
                unsigned int nbind;
         
     | 
| 
      
 168 
     | 
    
         
            +
                int addrdiff = 0;
         
     | 
| 
      
 169 
     | 
    
         
            +
                int i;
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                memset(segments, 0, sizeof(segments));
         
     | 
| 
      
 172 
     | 
    
         
            +
            #ifdef __LP64__
         
     | 
| 
      
 173 
     | 
    
         
            +
                cmd = (struct load_command *)((size_t)mh + sizeof(struct mach_header_64));
         
     | 
| 
      
 174 
     | 
    
         
            +
            #else
         
     | 
| 
      
 175 
     | 
    
         
            +
                cmd = (struct load_command *)((size_t)mh + sizeof(struct mach_header));
         
     | 
| 
      
 176 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 177 
     | 
    
         
            +
                for (i = 0; i < mh->ncmds; i++) {
         
     | 
| 
      
 178 
     | 
    
         
            +
                    struct dyld_info_command *dyld_info;
         
     | 
| 
      
 179 
     | 
    
         
            +
                    struct segment_command *segment;
         
     | 
| 
      
 180 
     | 
    
         
            +
                    struct segment_command_64 *segment64;
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                    switch (cmd->cmd) {
         
     | 
| 
      
 183 
     | 
    
         
            +
                    case LC_SEGMENT: /* 0x1 */
         
     | 
| 
      
 184 
     | 
    
         
            +
                        segment = (struct segment_command *)cmd;
         
     | 
| 
      
 185 
     | 
    
         
            +
                        DEBUG_CMD("LC_SEGMENT\n"
         
     | 
| 
      
 186 
     | 
    
         
            +
                                  "  segname   %s\n"
         
     | 
| 
      
 187 
     | 
    
         
            +
                                  "  vmaddr    %8x  vmsize     %8x\n"
         
     | 
| 
      
 188 
     | 
    
         
            +
                                  "  fileoff   %8x  filesize   %8x\n"
         
     | 
| 
      
 189 
     | 
    
         
            +
                                  "  maxprot   %8x  initprot   %8x\n"
         
     | 
| 
      
 190 
     | 
    
         
            +
                                  "  nsects    %8d  flags      %8x\n",
         
     | 
| 
      
 191 
     | 
    
         
            +
                                  segment->segname,
         
     | 
| 
      
 192 
     | 
    
         
            +
                                  segment->vmaddr, segment->vmsize,
         
     | 
| 
      
 193 
     | 
    
         
            +
                                  segment->fileoff, segment->filesize,
         
     | 
| 
      
 194 
     | 
    
         
            +
                                  segment->maxprot, segment->initprot,
         
     | 
| 
      
 195 
     | 
    
         
            +
                                  segment->nsects, segment->flags);
         
     | 
| 
      
 196 
     | 
    
         
            +
                        if (strcmp(segment->segname, "__LINKEDIT") == 0) {
         
     | 
| 
      
 197 
     | 
    
         
            +
                            addrdiff = segment->vmaddr - segment->fileoff;
         
     | 
| 
      
 198 
     | 
    
         
            +
                        }
         
     | 
| 
      
 199 
     | 
    
         
            +
            #ifndef __LP64__
         
     | 
| 
      
 200 
     | 
    
         
            +
                        segments[segment_idx++] = segment;
         
     | 
| 
      
 201 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 202 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 203 
     | 
    
         
            +
                    case LC_SEGMENT_64: /* 0x19 */
         
     | 
| 
      
 204 
     | 
    
         
            +
                        segment64 = (struct segment_command_64 *)cmd;
         
     | 
| 
      
 205 
     | 
    
         
            +
                        DEBUG_CMD("LC_SEGMENT_64\n"
         
     | 
| 
      
 206 
     | 
    
         
            +
                                  "  segname   %s\n"
         
     | 
| 
      
 207 
     | 
    
         
            +
                                  "  vmaddr    %8llx  vmsize     %8llx\n"
         
     | 
| 
      
 208 
     | 
    
         
            +
                                  "  fileoff   %8llx  filesize   %8llx\n"
         
     | 
| 
      
 209 
     | 
    
         
            +
                                  "  maxprot   %8x  initprot   %8x\n"
         
     | 
| 
      
 210 
     | 
    
         
            +
                                  "  nsects    %8d  flags      %8x\n",
         
     | 
| 
      
 211 
     | 
    
         
            +
                                  segment64->segname,
         
     | 
| 
      
 212 
     | 
    
         
            +
                                  segment64->vmaddr, segment64->vmsize,
         
     | 
| 
      
 213 
     | 
    
         
            +
                                  segment64->fileoff, segment64->filesize,
         
     | 
| 
      
 214 
     | 
    
         
            +
                                  segment64->maxprot, segment64->initprot,
         
     | 
| 
      
 215 
     | 
    
         
            +
                                  segment64->nsects, segment64->flags);
         
     | 
| 
      
 216 
     | 
    
         
            +
                        if (strcmp(segment64->segname, "__LINKEDIT") == 0) {
         
     | 
| 
      
 217 
     | 
    
         
            +
                            addrdiff = segment64->vmaddr - segment64->fileoff;
         
     | 
| 
      
 218 
     | 
    
         
            +
                        }
         
     | 
| 
      
 219 
     | 
    
         
            +
            #ifdef __LP64__
         
     | 
| 
      
 220 
     | 
    
         
            +
                        segments[segment_idx++] = segment64;
         
     | 
| 
      
 221 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 222 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 223 
     | 
    
         
            +
                    case LC_DYLD_INFO_ONLY: /* (0x22|LC_REQ_DYLD) */
         
     | 
| 
      
 224 
     | 
    
         
            +
                        dyld_info= (struct dyld_info_command *)cmd;
         
     | 
| 
      
 225 
     | 
    
         
            +
                        lazy_bind_off = dyld_info->lazy_bind_off;
         
     | 
| 
      
 226 
     | 
    
         
            +
                        lazy_bind_size = dyld_info->lazy_bind_size;
         
     | 
| 
      
 227 
     | 
    
         
            +
                        DEBUG_CMD("LC_DYLD_INFO_ONLY\n"
         
     | 
| 
      
 228 
     | 
    
         
            +
                                  "                 offset     size\n"
         
     | 
| 
      
 229 
     | 
    
         
            +
                                  "  rebase       %8x %8x\n"
         
     | 
| 
      
 230 
     | 
    
         
            +
                                  "  bind         %8x %8x\n"
         
     | 
| 
      
 231 
     | 
    
         
            +
                                  "  weak_bind    %8x %8x\n"
         
     | 
| 
      
 232 
     | 
    
         
            +
                                  "  lazy_bind    %8x %8x\n"
         
     | 
| 
      
 233 
     | 
    
         
            +
                                  "  export_bind  %8x %8x\n",
         
     | 
| 
      
 234 
     | 
    
         
            +
                                  dyld_info->rebase_off, dyld_info->rebase_size,
         
     | 
| 
      
 235 
     | 
    
         
            +
                                  dyld_info->bind_off, dyld_info->bind_size,
         
     | 
| 
      
 236 
     | 
    
         
            +
                                  dyld_info->weak_bind_off, dyld_info->weak_bind_size,
         
     | 
| 
      
 237 
     | 
    
         
            +
                                  dyld_info->lazy_bind_off, dyld_info->lazy_bind_size,
         
     | 
| 
      
 238 
     | 
    
         
            +
                                  dyld_info->export_off, dyld_info->export_size);
         
     | 
| 
      
 239 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 240 
     | 
    
         
            +
                    case LC_SYMTAB: /* 0x2 */
         
     | 
| 
      
 241 
     | 
    
         
            +
                        DEBUG_CMD("LC_SYMTAB\n");
         
     | 
| 
      
 242 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 243 
     | 
    
         
            +
                    case LC_DYSYMTAB: /* 0xb */
         
     | 
| 
      
 244 
     | 
    
         
            +
                        DEBUG_CMD("LC_DYSYMTAB\n");
         
     | 
| 
      
 245 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 246 
     | 
    
         
            +
                    case LC_LOAD_DYLIB: /* 0xc */
         
     | 
| 
      
 247 
     | 
    
         
            +
                        DEBUG_CMD("LC_LOAD_DYLIB\n");
         
     | 
| 
      
 248 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 249 
     | 
    
         
            +
                    case LC_ID_DYLIB: /* 0xd */
         
     | 
| 
      
 250 
     | 
    
         
            +
                        DEBUG_CMD("LC_ID_DYLIB\n");
         
     | 
| 
      
 251 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 252 
     | 
    
         
            +
                    case LC_LOAD_DYLINKER: /* 0xe */
         
     | 
| 
      
 253 
     | 
    
         
            +
                        DEBUG_CMD("LC_LOAD_DYLINKER\n");
         
     | 
| 
      
 254 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 255 
     | 
    
         
            +
                    case LC_ROUTINES_64: /* 0x1a */
         
     | 
| 
      
 256 
     | 
    
         
            +
                        DEBUG_CMD("LC_ROUTINES_64\n");
         
     | 
| 
      
 257 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 258 
     | 
    
         
            +
                    case LC_UUID: /* 0x1b */
         
     | 
| 
      
 259 
     | 
    
         
            +
                        DEBUG_CMD("LC_UUID\n");
         
     | 
| 
      
 260 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 261 
     | 
    
         
            +
                    case LC_VERSION_MIN_MACOSX: /* 0x24 */
         
     | 
| 
      
 262 
     | 
    
         
            +
                        DEBUG_CMD("LC_VERSION_MIN_MACOSX\n");
         
     | 
| 
      
 263 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 264 
     | 
    
         
            +
                    case LC_FUNCTION_STARTS: /* 0x26 */
         
     | 
| 
      
 265 
     | 
    
         
            +
                        DEBUG_CMD("LC_FUNCTION_STARTS\n");
         
     | 
| 
      
 266 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 267 
     | 
    
         
            +
                    case LC_MAIN: /* 0x28|LC_REQ_DYLD */
         
     | 
| 
      
 268 
     | 
    
         
            +
                        DEBUG_CMD("LC_MAIN\n");
         
     | 
| 
      
 269 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 270 
     | 
    
         
            +
                    case LC_DATA_IN_CODE: /* 0x29 */
         
     | 
| 
      
 271 
     | 
    
         
            +
                        DEBUG_CMD("LC_DATA_IN_CODE\n");
         
     | 
| 
      
 272 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 273 
     | 
    
         
            +
                    case LC_SOURCE_VERSION: /* 0x2A */
         
     | 
| 
      
 274 
     | 
    
         
            +
                        DEBUG_CMD("LC_SOURCE_VERSION\n");
         
     | 
| 
      
 275 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 276 
     | 
    
         
            +
                    case LC_DYLIB_CODE_SIGN_DRS: /* 0x2B */
         
     | 
| 
      
 277 
     | 
    
         
            +
                        DEBUG_CMD("LC_DYLIB_CODE_SIGN_DRS\n");
         
     | 
| 
      
 278 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 279 
     | 
    
         
            +
                    default:
         
     | 
| 
      
 280 
     | 
    
         
            +
                        DEBUG_CMD("LC_? (0x%x)\n", cmd->cmd);
         
     | 
| 
      
 281 
     | 
    
         
            +
                    }
         
     | 
| 
      
 282 
     | 
    
         
            +
                    cmd = (struct load_command *)((size_t)cmd + cmd->cmdsize);
         
     | 
| 
      
 283 
     | 
    
         
            +
                }
         
     | 
| 
      
 284 
     | 
    
         
            +
                nbind = get_bind_addr(NULL, base, lazy_bind_off, lazy_bind_size, segments, addrdiff);
         
     | 
| 
      
 285 
     | 
    
         
            +
                *plthook_out = (plthook_t*)malloc(offsetof(plthook_t, entries) + sizeof(bind_address_t) * nbind);
         
     | 
| 
      
 286 
     | 
    
         
            +
                (*plthook_out)->num_entries = nbind;
         
     | 
| 
      
 287 
     | 
    
         
            +
                get_bind_addr(*plthook_out, base, lazy_bind_off, lazy_bind_size, segments, addrdiff);
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 290 
     | 
    
         
            +
            }
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
      
 292 
     | 
    
         
            +
            static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint32_t lazy_bind_off, uint32_t lazy_bind_size, struct segment_command_ **segments, int addrdiff)
         
     | 
| 
      
 293 
     | 
    
         
            +
            {
         
     | 
| 
      
 294 
     | 
    
         
            +
                const uint8_t *ptr = base + lazy_bind_off + addrdiff;
         
     | 
| 
      
 295 
     | 
    
         
            +
                const uint8_t *end = ptr + lazy_bind_size;
         
     | 
| 
      
 296 
     | 
    
         
            +
                const char *sym_name;
         
     | 
| 
      
 297 
     | 
    
         
            +
                int seg_index = 0;
         
     | 
| 
      
 298 
     | 
    
         
            +
                uint64_t seg_offset = 0;
         
     | 
| 
      
 299 
     | 
    
         
            +
                int count, skip;
         
     | 
| 
      
 300 
     | 
    
         
            +
                unsigned int idx;
         
     | 
| 
      
 301 
     | 
    
         
            +
                DEBUG_BIND("get_bind_addr(%p, 0x%x, 0x%x", base, lazy_bind_off, lazy_bind_size);
         
     | 
| 
      
 302 
     | 
    
         
            +
                for (idx = 0; segments[idx] != NULL; idx++) {
         
     | 
| 
      
 303 
     | 
    
         
            +
                    DEBUG_BIND(", [%s]", segments[idx]->segname);
         
     | 
| 
      
 304 
     | 
    
         
            +
                }
         
     | 
| 
      
 305 
     | 
    
         
            +
                DEBUG_BIND(")\n");
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
      
 307 
     | 
    
         
            +
                idx = 0;
         
     | 
| 
      
 308 
     | 
    
         
            +
                while (ptr < end) {
         
     | 
| 
      
 309 
     | 
    
         
            +
                    uint8_t op = *ptr & BIND_OPCODE_MASK;
         
     | 
| 
      
 310 
     | 
    
         
            +
                    uint8_t imm = *ptr & BIND_IMMEDIATE_MASK;
         
     | 
| 
      
 311 
     | 
    
         
            +
                    uint64_t ulebval;
         
     | 
| 
      
 312 
     | 
    
         
            +
                    int64_t slebval;
         
     | 
| 
      
 313 
     | 
    
         
            +
                    int i;
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                    DEBUG_BIND("0x%02x: ", *ptr);
         
     | 
| 
      
 316 
     | 
    
         
            +
                    ptr++;
         
     | 
| 
      
 317 
     | 
    
         
            +
                    switch (op) {
         
     | 
| 
      
 318 
     | 
    
         
            +
                    case BIND_OPCODE_DONE:
         
     | 
| 
      
 319 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_DONE\n");
         
     | 
| 
      
 320 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 321 
     | 
    
         
            +
                    case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
         
     | 
| 
      
 322 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: ordinal = %u\n", imm);
         
     | 
| 
      
 323 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 324 
     | 
    
         
            +
                    case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
         
     | 
| 
      
 325 
     | 
    
         
            +
                        ulebval = uleb128(&ptr);
         
     | 
| 
      
 326 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: ordinal = %llu\n", ulebval);
         
     | 
| 
      
 327 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 328 
     | 
    
         
            +
                    case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
         
     | 
| 
      
 329 
     | 
    
         
            +
                        if (imm == 0) {
         
     | 
| 
      
 330 
     | 
    
         
            +
                            DEBUG_BIND("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: ordinal = 0\n");
         
     | 
| 
      
 331 
     | 
    
         
            +
                        } else {
         
     | 
| 
      
 332 
     | 
    
         
            +
                            DEBUG_BIND("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: ordinal = %u\n", BIND_OPCODE_MASK | imm);
         
     | 
| 
      
 333 
     | 
    
         
            +
                        }
         
     | 
| 
      
 334 
     | 
    
         
            +
                    case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
         
     | 
| 
      
 335 
     | 
    
         
            +
                        sym_name = (const char*)ptr;
         
     | 
| 
      
 336 
     | 
    
         
            +
                        ptr += strlen(sym_name) + 1;
         
     | 
| 
      
 337 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: sym_name = %s\n", sym_name);
         
     | 
| 
      
 338 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 339 
     | 
    
         
            +
                    case BIND_OPCODE_SET_TYPE_IMM:
         
     | 
| 
      
 340 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_SET_TYPE_IMM: type = %u\n", imm);
         
     | 
| 
      
 341 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 342 
     | 
    
         
            +
                    case BIND_OPCODE_SET_ADDEND_SLEB:
         
     | 
| 
      
 343 
     | 
    
         
            +
                        slebval = sleb128(&ptr);
         
     | 
| 
      
 344 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_SET_ADDEND_SLEB: ordinal = %lld\n", slebval);
         
     | 
| 
      
 345 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 346 
     | 
    
         
            +
                    case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
         
     | 
| 
      
 347 
     | 
    
         
            +
                        seg_index = imm;
         
     | 
| 
      
 348 
     | 
    
         
            +
                        seg_offset = uleb128(&ptr);
         
     | 
| 
      
 349 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: seg_index = %u, seg_offset = 0x%llx\n", seg_index, seg_offset);
         
     | 
| 
      
 350 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 351 
     | 
    
         
            +
                    case BIND_OPCODE_ADD_ADDR_ULEB:
         
     | 
| 
      
 352 
     | 
    
         
            +
                        seg_offset += uleb128(&ptr);
         
     | 
| 
      
 353 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_ADD_ADDR_ULEB: seg_offset = 0x%llx\n", seg_offset);
         
     | 
| 
      
 354 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 355 
     | 
    
         
            +
                    case BIND_OPCODE_DO_BIND:
         
     | 
| 
      
 356 
     | 
    
         
            +
                        set_bind_addr(&idx, plthook, base, sym_name, seg_index, seg_offset, segments);
         
     | 
| 
      
 357 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_DO_BIND\n");
         
     | 
| 
      
 358 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 359 
     | 
    
         
            +
                    case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
         
     | 
| 
      
 360 
     | 
    
         
            +
                        seg_offset += uleb128(&ptr);
         
     | 
| 
      
 361 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: seg_offset = 0x%llx\n", seg_offset);
         
     | 
| 
      
 362 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 363 
     | 
    
         
            +
                    case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
         
     | 
| 
      
 364 
     | 
    
         
            +
                        set_bind_addr(&idx, plthook, base, sym_name, seg_index, seg_offset, segments);
         
     | 
| 
      
 365 
     | 
    
         
            +
                        seg_offset += imm * sizeof(void *);
         
     | 
| 
      
 366 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
         
     | 
| 
      
 367 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 368 
     | 
    
         
            +
                    case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
         
     | 
| 
      
 369 
     | 
    
         
            +
                        count = uleb128(&ptr);
         
     | 
| 
      
 370 
     | 
    
         
            +
                        skip = uleb128(&ptr);
         
     | 
| 
      
 371 
     | 
    
         
            +
                        for (i = 0; i < count; i++) {
         
     | 
| 
      
 372 
     | 
    
         
            +
                            set_bind_addr(&idx, plthook, base, sym_name, seg_index, seg_offset, segments);
         
     | 
| 
      
 373 
     | 
    
         
            +
                            seg_offset += skip;
         
     | 
| 
      
 374 
     | 
    
         
            +
                        }
         
     | 
| 
      
 375 
     | 
    
         
            +
                        DEBUG_BIND("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB\n");
         
     | 
| 
      
 376 
     | 
    
         
            +
                        break;
         
     | 
| 
      
 377 
     | 
    
         
            +
                    }
         
     | 
| 
      
 378 
     | 
    
         
            +
                }
         
     | 
| 
      
 379 
     | 
    
         
            +
                return idx;
         
     | 
| 
      
 380 
     | 
    
         
            +
            }
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
            static void set_bind_addr(unsigned int *idx, plthook_t *plthook, const uint8_t *base, const char *sym_name, int seg_index, int seg_offset, struct segment_command_ **segments)
         
     | 
| 
      
 383 
     | 
    
         
            +
            {
         
     | 
| 
      
 384 
     | 
    
         
            +
                if (plthook != NULL) {
         
     | 
| 
      
 385 
     | 
    
         
            +
                    uint32_t vmaddr = segments[seg_index]->vmaddr;
         
     | 
| 
      
 386 
     | 
    
         
            +
                    plthook->entries[*idx].name = sym_name;
         
     | 
| 
      
 387 
     | 
    
         
            +
                    plthook->entries[*idx].addr = (void**)(base + vmaddr + seg_offset);
         
     | 
| 
      
 388 
     | 
    
         
            +
                }
         
     | 
| 
      
 389 
     | 
    
         
            +
                (*idx)++;
         
     | 
| 
      
 390 
     | 
    
         
            +
            }
         
     | 
| 
      
 391 
     | 
    
         
            +
             
     | 
| 
      
 392 
     | 
    
         
            +
            int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
         
     | 
| 
      
 393 
     | 
    
         
            +
            {
         
     | 
| 
      
 394 
     | 
    
         
            +
                if (*pos >= plthook->num_entries) {
         
     | 
| 
      
 395 
     | 
    
         
            +
                    *name_out = NULL;
         
     | 
| 
      
 396 
     | 
    
         
            +
                    *addr_out = NULL;
         
     | 
| 
      
 397 
     | 
    
         
            +
                    return EOF;
         
     | 
| 
      
 398 
     | 
    
         
            +
                }
         
     | 
| 
      
 399 
     | 
    
         
            +
                *name_out = plthook->entries[*pos].name;
         
     | 
| 
      
 400 
     | 
    
         
            +
                *addr_out = plthook->entries[*pos].addr;
         
     | 
| 
      
 401 
     | 
    
         
            +
                (*pos)++;
         
     | 
| 
      
 402 
     | 
    
         
            +
                return 0;
         
     | 
| 
      
 403 
     | 
    
         
            +
            }
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
            int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, void **oldfunc)
         
     | 
| 
      
 406 
     | 
    
         
            +
            {
         
     | 
| 
      
 407 
     | 
    
         
            +
                size_t funcnamelen = strlen(funcname);
         
     | 
| 
      
 408 
     | 
    
         
            +
                unsigned int pos = 0;
         
     | 
| 
      
 409 
     | 
    
         
            +
                const char *name;
         
     | 
| 
      
 410 
     | 
    
         
            +
                void **addr;
         
     | 
| 
      
 411 
     | 
    
         
            +
                int rv;
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
                if (plthook == NULL) {
         
     | 
| 
      
 414 
     | 
    
         
            +
                    set_errmsg("invalid argument: The first argument is null.");
         
     | 
| 
      
 415 
     | 
    
         
            +
                    return PLTHOOK_INVALID_ARGUMENT;
         
     | 
| 
      
 416 
     | 
    
         
            +
                }
         
     | 
| 
      
 417 
     | 
    
         
            +
                while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
         
     | 
| 
      
 418 
     | 
    
         
            +
                    if (strncmp(name, funcname, funcnamelen) == 0) {
         
     | 
| 
      
 419 
     | 
    
         
            +
                        if (name[funcnamelen] == '\0' || name[funcnamelen] == '$') {
         
     | 
| 
      
 420 
     | 
    
         
            +
                            goto matched;
         
     | 
| 
      
 421 
     | 
    
         
            +
                        }
         
     | 
| 
      
 422 
     | 
    
         
            +
                    }
         
     | 
| 
      
 423 
     | 
    
         
            +
                    if (name[0] == '@') {
         
     | 
| 
      
 424 
     | 
    
         
            +
                        /* Oracle libclntsh.dylib imports 'read' as '@_read'. */
         
     | 
| 
      
 425 
     | 
    
         
            +
                        name++;
         
     | 
| 
      
 426 
     | 
    
         
            +
                        if (strncmp(name, funcname, funcnamelen) == 0) {
         
     | 
| 
      
 427 
     | 
    
         
            +
                            if (name[funcnamelen] == '\0' || name[funcnamelen] == '$') {
         
     | 
| 
      
 428 
     | 
    
         
            +
                                goto matched;
         
     | 
| 
      
 429 
     | 
    
         
            +
                            }
         
     | 
| 
      
 430 
     | 
    
         
            +
                        }
         
     | 
| 
      
 431 
     | 
    
         
            +
                    }
         
     | 
| 
      
 432 
     | 
    
         
            +
                    if (name[0] == '_') {
         
     | 
| 
      
 433 
     | 
    
         
            +
                        name++;
         
     | 
| 
      
 434 
     | 
    
         
            +
                        if (strncmp(name, funcname, funcnamelen) == 0) {
         
     | 
| 
      
 435 
     | 
    
         
            +
                            if (name[funcnamelen] == '\0' || name[funcnamelen] == '$') {
         
     | 
| 
      
 436 
     | 
    
         
            +
                                goto matched;
         
     | 
| 
      
 437 
     | 
    
         
            +
                            }
         
     | 
| 
      
 438 
     | 
    
         
            +
                        }
         
     | 
| 
      
 439 
     | 
    
         
            +
                    }
         
     | 
| 
      
 440 
     | 
    
         
            +
                    continue;
         
     | 
| 
      
 441 
     | 
    
         
            +
            matched:
         
     | 
| 
      
 442 
     | 
    
         
            +
                    if (oldfunc) {
         
     | 
| 
      
 443 
     | 
    
         
            +
                        *oldfunc = *addr;
         
     | 
| 
      
 444 
     | 
    
         
            +
                    }
         
     | 
| 
      
 445 
     | 
    
         
            +
                    *addr = funcaddr;
         
     | 
| 
      
 446 
     | 
    
         
            +
                    return 0;
         
     | 
| 
      
 447 
     | 
    
         
            +
                }
         
     | 
| 
      
 448 
     | 
    
         
            +
                if (rv == EOF) {
         
     | 
| 
      
 449 
     | 
    
         
            +
                    set_errmsg("no such function: %s", funcname);
         
     | 
| 
      
 450 
     | 
    
         
            +
                    rv = PLTHOOK_FUNCTION_NOT_FOUND;
         
     | 
| 
      
 451 
     | 
    
         
            +
                }
         
     | 
| 
      
 452 
     | 
    
         
            +
                return rv;
         
     | 
| 
      
 453 
     | 
    
         
            +
            }
         
     | 
| 
      
 454 
     | 
    
         
            +
             
     | 
| 
      
 455 
     | 
    
         
            +
            void plthook_close(plthook_t *plthook)
         
     | 
| 
      
 456 
     | 
    
         
            +
            {
         
     | 
| 
      
 457 
     | 
    
         
            +
                if (plthook != NULL) {
         
     | 
| 
      
 458 
     | 
    
         
            +
                    free(plthook);
         
     | 
| 
      
 459 
     | 
    
         
            +
                }
         
     | 
| 
      
 460 
     | 
    
         
            +
                return;
         
     | 
| 
      
 461 
     | 
    
         
            +
            }
         
     | 
| 
      
 462 
     | 
    
         
            +
             
     | 
| 
      
 463 
     | 
    
         
            +
            const char *plthook_error(void)
         
     | 
| 
      
 464 
     | 
    
         
            +
            {
         
     | 
| 
      
 465 
     | 
    
         
            +
                return errmsg;
         
     | 
| 
      
 466 
     | 
    
         
            +
            }
         
     | 
| 
      
 467 
     | 
    
         
            +
             
     | 
| 
      
 468 
     | 
    
         
            +
            static void set_errmsg(const char *fmt, ...)
         
     | 
| 
      
 469 
     | 
    
         
            +
            {
         
     | 
| 
      
 470 
     | 
    
         
            +
                va_list ap;
         
     | 
| 
      
 471 
     | 
    
         
            +
                va_start(ap, fmt);
         
     | 
| 
      
 472 
     | 
    
         
            +
                vsnprintf(errmsg, sizeof(errmsg) - 1, fmt, ap);
         
     | 
| 
      
 473 
     | 
    
         
            +
                va_end(ap);
         
     | 
| 
      
 474 
     | 
    
         
            +
            }
         
     |