Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / symtab / test_relocations.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "symtab_comp.h"
33 #include "test_lib.h"
34
35 #include "Symtab.h"
36 #include "Symbol.h"
37 #include "Function.h"
38 #include "Variable.h"
39
40 #include <iostream>
41 #include <errno.h>
42 #if !defined(os_windows_test)
43 #include <dirent.h>
44 #endif
45
46 using namespace Dyninst;
47 using namespace SymtabAPI;
48
49 bool resolve_libc_name(char *buf)
50 {
51 #if defined(os_windows_test)
52         return false;
53 #else
54         DIR *dirp;
55         struct dirent *dp;
56
57         if (NULL == (dirp = opendir("/lib"))) 
58         {
59                 fprintf(stderr, "%s[%d]: couldn’t open /lib: %s", FILE__, __LINE__, strerror(errno));
60                 return false;
61         }
62
63         do {
64                 errno = 0;
65                 if ((dp = readdir(dirp)) != NULL) {
66                         int nelem = strlen("libc.so");
67                         if ( 0 != strncmp(dp->d_name, "libc.so", nelem))
68                                 continue;
69
70                         dprintf("found %s\n", dp->d_name);
71                         sprintf(buf, "/lib/%s", dp->d_name);
72                         closedir(dirp);
73                         return true;
74
75                 }
76         } while (dp != NULL);
77
78         return false;
79 #endif
80 }
81
82 class test_relocations_Mutator : public SymtabMutator {
83         std::vector<relocationEntry> relocs;
84         char libc_name[128];
85         Symtab *libc;
86         std::vector<std::string> expected_libc_relocations;
87
88         bool open_libc()
89         {
90                 if (!resolve_libc_name(libc_name))
91                 {
92                         fprintf(stderr, "%s[%d]:  cannot find libc....\n", FILE__, __LINE__);
93                         return false;
94                 }
95
96                 if (!Symtab::openFile(libc, libc_name))
97                 {
98                         fprintf(stderr, "%s[%d]:  cannot create libc....\n", FILE__, __LINE__);
99                         return false;
100                 }
101
102                 return true;
103         }
104
105         public:
106         test_relocations_Mutator() 
107         { 
108                 expected_libc_relocations.push_back(std::string("printf"));
109                 expected_libc_relocations.push_back(std::string("fprintf"));
110                 expected_libc_relocations.push_back(std::string("sprintf"));
111                 expected_libc_relocations.push_back(std::string("snprintf"));
112                 expected_libc_relocations.push_back(std::string("memcpy"));
113                 expected_libc_relocations.push_back(std::string("strcmp"));
114                 expected_libc_relocations.push_back(std::string("memset"));
115                 expected_libc_relocations.push_back(std::string("fopen"));
116                 expected_libc_relocations.push_back(std::string("fwrite"));
117                 expected_libc_relocations.push_back(std::string("fread"));
118                 expected_libc_relocations.push_back(std::string("fclose"));
119                 expected_libc_relocations.push_back(std::string("__xstat"));
120                 expected_libc_relocations.push_back(std::string("__lxstat"));
121                 expected_libc_relocations.push_back(std::string("__fxstat"));
122         };
123         virtual test_results_t executeTest();
124 };
125
126 extern "C" DLLEXPORT TestMutator* test_relocations_factory()
127 {
128         return new test_relocations_Mutator();
129 }
130
131 test_results_t test_relocations_Mutator::executeTest()
132 {
133 #if defined (os_windows_test)
134         return SKIPPED;
135 #endif
136
137 #if defined (os_aix_test)
138         return SKIPPED;
139 #endif
140
141         bool result = symtab->getFuncBindingTable(relocs);
142
143         if (!result || !relocs.size() )
144         {
145                 logerror("%s[%d]: - Unable to find relocations\n", 
146                                 FILE__, __LINE__);
147                 return FAILED;
148         }
149
150 #if 0
151         fprintf(stderr, "%s[%d]:  have relocs:\n", FILE__, __LINE__);
152         for (unsigned int i = 0; i < relocs.size(); ++i)
153         {
154            Symbol *s = relocs[i].getDynSym();
155            std::cerr << "      " <<  relocs[i];
156            if (s)
157                   std::cerr << "  symname:  " << s->getName() << "  symaddr: " <<s->getAddr() << " symtype = "<< Symbol::symbolType2Str(s->getType()) << "symlinkage = " <<Symbol::symbolLinkage2Str(s->getLinkage()) << " vis = " <<Symbol::symbolVisibility2Str(s->getVisibility()); 
158            std::cerr << std::endl;
159    }
160 #endif
161
162         if (!open_libc())
163         {
164                 fprintf(stderr, "%s[%d]:  failed to open libc\n", FILE__, __LINE__);
165                 return FAILED;
166         }
167
168
169         bool found_one = false;
170
171         for (unsigned int i = 0; i < expected_libc_relocations.size(); ++i)
172         {
173                 int relocation_index ;
174                 bool found = false;
175                 for (unsigned int j = 0; j < relocs.size(); ++j)
176                 {
177                         const std::string &relname = relocs[j].name();
178                         if (relname == expected_libc_relocations[i])
179                         {
180                                 found = true;
181                                 relocation_index = i;
182                                 break;
183                         }
184                 }
185                 if (!found)
186                 {
187 #if 0
188                         fprintf(stderr, "%s[%d]:  could not find relocation for %s\n", 
189                                         FILE__, __LINE__, expected_libc_relocations[i].c_str());
190 #endif
191                 }
192                 else 
193                 {
194                         std::vector<Function *> libc_matches;
195                         if (!libc->findFunctionsByName(libc_matches, expected_libc_relocations[i]) 
196                                         || !libc_matches.size())
197                         {
198 #if 0
199                                 fprintf(stderr, "%s[%d]:  failed to find %s in libc\n", FILE__, __LINE__, 
200                                                 expected_libc_relocations[i].c_str());
201                                 err = true;
202 #endif
203                         }
204                         else
205                         {
206                                 //fprintf(stderr, "%s[%d]:  found %d matches for %s in libc\n", 
207                         //                      FILE__, __LINE__, libc_matches.size(), expected_libc_relocations[i].c_str());
208
209                                 found_one = true;
210 #if 0
211                                 const Dyninst::SymtabAPI::Function *f = libc_matches[0];
212
213                                 if (!f)
214                                 {
215                                         fprintf(stderr, "%s[%d]:  BAD NEWS:  symtabAPI returned NULL func\n", 
216                                                         FILE__, __LINE__);
217                                         err = true;
218                                 }
219                                 else 
220                                 {
221                                         //  maybe eventually we can check that the relocation address
222                                         //  properly resolve to the library...  for now existence 
223                                         //  will have to suffice.
224                                         Offset off = f->getOffset();
225                                         //fprintf(stderr, "\toffset = %p, rel_target_addr = %p, rel_addr = %p\n", 
226                                         // off, relocs[relocation_index].target_addr(), relocs[relocation_index].rel_addr());
227                                 }
228 #endif
229                         }
230                 }
231         }
232
233         if (!found_one) 
234         {
235 #if 0
236                 fprintf(stderr, "%s[%d]:  have relocations:\n", FILE__, __LINE__);
237                 for (unsigned int i = 0; i < relocs.size(); ++i)
238                 {
239                         std::cerr << "        " << relocs[i] << std::endl;
240
241                 }
242 #endif
243                 return FAILED;
244         }
245
246         //  OK, enough with libc...  now let's look at the (more controllable) relocations
247         //  from libtestA...
248
249         std::vector<std::string> expected_relocs;
250         expected_relocs.push_back(std::string("relocation_test_function1"));
251         expected_relocs.push_back(std::string("relocation_test_function2"));
252         //expected_relocs.push_back(std::string("relocation_test_variable1"));
253         //expected_relocs.push_back(std::string("relocation_test_variable2"));
254         int num_found = 0;
255         for (unsigned int i = 0; i < expected_relocs.size(); ++i)
256         {
257                 bool foundit =  false;
258                 for (unsigned int j = 0; j < relocs.size(); ++j)
259                 {
260                         if (relocs[j].name() == expected_relocs[i])
261                         {
262                                 foundit = true;
263                                 num_found++;
264                                 break;
265                         }
266                 }
267                 if (!foundit)
268                         fprintf(stderr, "%s[%d]:  failed to find relocation for %s\n", 
269                                         FILE__, __LINE__, expected_relocs[i].c_str());
270         }
271
272         if (num_found != expected_relocs.size())
273         {
274                 fprintf(stderr, "%s[%d]:  found %d relocs, not the expected %d\n", 
275                                 FILE__, __LINE__, num_found, expected_relocs.size());
276                 return FAILED;
277         }
278         return PASSED;
279 }
280