1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <stdio.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <getopt.h>
33#include <string.h>
34#include <dlfcn.h>
35
36extern char *optarg;
37extern int optind, opterr, optopt;
38
39static struct option long_options[] = {
40    {"library", required_argument, 0, 'l'},
41    {"symbol",  required_argument, 0, 's'},
42    {"help",    no_argument,       0, 'h'},
43    {0, 0, 0, 0},
44};
45
46/* This array must parallel long_options[] */
47static const char *descriptions[] = {
48    "specify a library path to look up symbol",
49    "specify symbol to look up",
50    "print this help screen",
51};
52
53void print_help(const char *name) {
54    fprintf(stdout,
55            "invokation:\n"
56            "\t%s [-l <libname>] -s <symbol name>\n"
57            "\t%s -h\n\n", name, name);
58    fprintf(stdout, "options:\n");
59    struct option *opt = long_options;
60    const char **desc = descriptions;
61    while (opt->name) {
62        fprintf(stdout, "\t-%c/--%s%s: %s\n",
63                opt->val,
64                opt->name,
65                (opt->has_arg ? " (argument)" : ""),
66                *desc);
67        opt++;
68        desc++;
69    }
70}
71
72int get_options(int argc, char **argv, char **lib, char **sym)
73{
74    int c;
75
76    *lib = 0;
77    *sym = 0;
78
79    while (1) {
80        /* getopt_long stores the option index here. */
81        int option_index = 0;
82
83        c = getopt_long (argc, argv,
84                         "l:s:h",
85                         long_options,
86                         &option_index);
87        /* Detect the end of the options. */
88        if (c == -1) break;
89
90        switch (c) {
91		case 'l':
92            *lib = strdup(optarg);
93			break;
94        case 's':
95            *sym = strdup(optarg);
96            break;
97        case 'h': print_help(argv[0]); exit(EXIT_FAILURE); break;
98        case '?':
99            /* getopt_long already printed an error message. */
100            break;
101        default:
102            fprintf(stderr, "Unknown option");
103            exit(EXIT_FAILURE);
104        }
105    }
106
107    return optind;
108}
109
110int main(int argc, char **argv)
111{
112    char *libname, *symname, *prog = *argv;
113
114    get_options(argc, argv, &libname, &symname);
115
116    if (symname == NULL) {
117        fprintf(stderr, "You must specify a symbol!\n");
118        print_help(prog);
119        exit(EXIT_FAILURE);
120    }
121
122    {
123        const char *dlerr;
124        void *handle, *symbol;
125
126        printf("opening library [%s]\n", libname);
127        dlerr = dlerror();
128        handle = libname ? dlopen(libname, RTLD_NOW) : RTLD_DEFAULT;
129        dlerr = dlerror();
130        if (dlerr != NULL) fprintf(stderr, "dlopen() error: %s\n", dlerr);
131
132        printf("opening symbol [%s]\n", symname);
133        symbol = dlsym(handle, symname);
134        dlerr = dlerror();
135        if (dlerr != NULL) fprintf(stderr, "dlsym() error: %s\n", dlerr);
136
137        printf("closing library [%s]\n", libname);
138        dlclose(handle);
139        dlerr = dlerror();
140        if (dlerr != NULL) fprintf(stderr, "dlclose() error: %s\n", dlerr);
141        else printf("successfully opened symbol\n");
142    }
143
144    if (libname != NULL) free(libname);
145    if (symname != NULL) free(symname);
146    return 0;
147}
148