Fix bug 1063; Function::addMangledName (also Variable::addMangledName) now creates...
[dyninst.git] / testsuite / src / symtab / test_add_symbols.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 using namespace Dyninst;
41 using namespace SymtabAPI;
42
43 class test_add_symbols_Mutator : public SymtabMutator {
44 public:
45    test_add_symbols_Mutator() { };
46    virtual test_results_t executeTest();
47 };
48
49 extern "C" DLLEXPORT TestMutator* test_add_symbols_factory()
50 {
51    return new test_add_symbols_Mutator();
52 }
53
54 test_results_t test_add_symbols_Mutator::executeTest()
55 {
56   if (useAttach == DESERIALIZE)
57     return SKIPPED;
58
59   // Test 1 of 2: add a name to a function
60   // Test 2 of 2: directly add a symbol into the image
61   
62   // Test 1 of 2
63   // Find the test function
64
65   std::vector<Function *> funcs;
66   bool result = symtab->findFunctionsByName(funcs, std::string("add_sym_func"));
67   
68   if (!result || !funcs.size() ) {
69     logerror("[%s:%u] - Unable to find test_add_symbols\n", 
70              __FILE__, __LINE__);
71     return FAILED;
72   }
73   
74   if (funcs.size() != 1) {
75     logerror("[%s:%u] - Too many functions found??: %d\n", 
76              __FILE__, __LINE__, funcs.size());
77     return FAILED;
78   }
79   
80   Function *f  = funcs[0];
81   
82   if (!f) {
83     logerror("[%s:%u] - NULL function returned\n", 
84              __FILE__, __LINE__);
85     return FAILED;
86   }
87   
88   if (0 == f->getOffset()) {
89     logerror("[%s:%u] - function with zero offset\n", 
90              __FILE__, __LINE__);
91     return FAILED;
92   }
93
94   // Get the pre-added symbols
95   std::vector<Symbol *> oldSyms;
96   f->getSymbols(oldSyms);
97
98   // That was long and involved. Now, add a name
99   if (!f->addMangledName("add_sym_func_newname", false)) {
100     logerror("[%s:%u]: failed to add name to function\n", __FILE__, __LINE__);
101     return FAILED;
102   }
103
104   // Now wasn't that nice. 
105
106   vector<Symbol *> syms;
107   f->getSymbols(syms);
108   if (syms.size() != (oldSyms.size() + 1)) {
109     logerror("[%s:%u] - function has %d symbols, expected %d\n",
110              __FILE__, __LINE__, syms.size(), oldSyms.size() + 1);
111     for (unsigned i = 0; i < syms.size(); ++i) {
112       logerror("\t %s (%p) (0x%lx) (%s)\n",
113                syms[i]->getMangledName().c_str(), 
114                syms[i], 
115                syms[i]->getOffset(),
116                syms[i]->isInDynSymtab() ? "<dyn>" : "<stat>");
117     }
118     return FAILED;
119   }
120
121   // Test 2 of 2: directly adding a symbol. We will copy it
122   // off of add_sym_func to make life easy. 
123   
124   Symbol *newsym = new Symbol("add_sym_newsymbol",
125                               Symbol::ST_FUNCTION,
126                               Symbol::SL_GLOBAL,
127                               Symbol::SV_DEFAULT,
128                               syms[0]->getOffset(),
129                               syms[0]->getModule(),
130                               syms[0]->getRegion());
131   if (!symtab->addSymbol(newsym)) {
132     logerror("[%s:%u]: failed to add symbol\n", __FILE__, __LINE__);
133     return FAILED;
134   }
135
136   // Test mechanism
137   // We emit this as a new file, re-read it, and go
138   // symbol hunting. 
139   
140   // 1) Create the directory and file
141   if (mkdir("./binaries", 0755)) {
142     if (errno != EEXIST) {
143       logerror("[%s:%u]: failed to create ./binaries directory\n", __FILE__, __LINE__);
144       return FAILED;
145     }
146   }
147
148   // 2) Emit this into a tmpfile
149   char *filename = strdup("./binaries/test_add_syms_XXXXXX");
150   mkstemp(filename);
151   if (!symtab->emit(filename)) {
152     logerror("[%s:%u]: failed to emit test to %s\n", __FILE__, __LINE__, filename);
153     return FAILED;
154   }
155
156   // 3) Reread it
157   Symtab *newSymtab = NULL;
158   if (!Symtab::openFile(newSymtab, filename)) {
159     logerror("[%s:%u]: failed to open %s\n", __FILE__, __LINE__, filename);
160     return FAILED;
161   }
162
163   // 4) And look for our added symbol...
164   std::vector<Symbol *> lookupSyms;
165   if (!newSymtab->findSymbol(lookupSyms, "add_sym_newsymbol")) {
166     logerror("[%s:%u]: failed to find symbol add_sym_newsymbol\n", __FILE__, __LINE__);
167     return FAILED;
168   }
169   if (lookupSyms.size() != 1) {
170     logerror("[%s:%u]: got unexpected number of symbols matching add_sym_newsymbol: %d != 1\n", __FILE__, __LINE__, lookupSyms.size());
171     return FAILED;
172   }
173   if (lookupSyms[0]->getOffset() != syms[0]->getOffset()) {
174     logerror("[%s:%u]: added symbol offset 0x%lx not equal to expected 0x%lx\n", __FILE__, __LINE__,
175              lookupSyms[0]->getOffset(), syms[0]->getOffset());
176     return FAILED;
177   }
178
179   // 5) And function name
180   std::vector<Function *> lookupFunc;
181   if (!newSymtab->findFunctionsByName(lookupFunc, "add_sym_func_newname")) {
182     logerror("[%s:%u]: failed to find function named add_sym_func_newname\n", __FILE__, __LINE__);
183     return FAILED;
184   }
185
186   if (lookupFunc.size() != 1) {
187     logerror("[%s:%u]: unexpected number of functions named add_sym_func_newname: %d != 1\n", __FILE__, __LINE__, lookupFunc.size());
188     return FAILED;
189   }
190
191   // Should check whether this is the right function...
192
193   // 6) We're good. 
194   unlink(filename);
195   free(filename);
196
197    return PASSED;
198 }
199