Build fix for AIX
[dyninst.git] / common / src / addrtranslate-aix.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 "common/h/addrtranslate.h"
33 #include "common/h/headers.h"
34
35 #include "symtabAPI/h/Symtab.h"
36 #include "symtabAPI/h/Archive.h"
37
38 #include <sys/procfs.h>
39 #include <string.h>
40 #include <string>
41 #include <vector>
42 #include <map>
43
44 namespace Dyninst {
45
46 class AddressTranslateAIX : public AddressTranslate
47 {
48 public:
49    AddressTranslateAIX(SymbolReaderFactory *fact_);
50    AddressTranslateAIX(PID pid, SymbolReaderFactory *fact_);
51
52    virtual bool refresh();
53    virtual ~AddressTranslateAIX();
54    Address getLibraryTrapAddrSysV();
55 };
56
57 class LoadedLibAIX : public LoadedLib {
58 protected:
59    string object;
60
61    mutable Address real_codeBase;
62    mutable Address real_dataBase;
63    mutable Address imageOffset;
64    mutable Address dataOffset;   
65    mutable bool reals_set;
66    void setReals() const;
67 public:
68    LoadedLibAIX(string name, Address load_addr, string object);
69    
70    virtual ~LoadedLibAIX();
71
72    virtual Address offToAddress(Offset off);
73    virtual Offset addrToOffset(Address addr);
74
75    virtual Address getCodeLoadAddr() const;
76    virtual Address getDataLoadAddr() const;
77    virtual void getOutputs(string &filename, Address &code, Address &data);
78 };
79
80 static int open_map_fd(PID pid)
81 {
82    char file[64];
83    snprintf(file, 64, "/proc/%d/map", pid);
84    int fd = P_open(file, O_RDONLY, pid);
85    return fd;
86 }
87
88 static char *deref_link(char *path)
89 {
90    static char buffer[PATH_MAX], *p;
91    buffer[PATH_MAX-1] = '\0';
92    p = realpath(path, buffer);
93    if (p)
94       return p;
95    return path;
96 }
97
98 bool AddressTranslateAIX::refresh()
99 {
100    unsigned iter = 0;
101    bool is_aout = true;
102    int map_fd = -1;
103    int result;
104    if (!pid)
105       return true;
106    
107    for (unsigned i=0; i<libs.size(); i++) {
108       if (libs[i])
109          delete libs[i];
110    }
111    libs.clear();
112    
113    map_fd = open_map_fd(pid);
114    if (map_fd == -1)
115       return false;
116
117    prmap_t mapEntry;
118
119 #if defined(DEBUG_PRINT)
120    for (;;) {
121       result = pread(map_fd, &mapEntry, sizeof(prmap_t), iter * sizeof(prmap_t));
122       if (result != sizeof(prmap_t))
123          break;
124       if (mapEntry.pr_size == 0)
125          break;
126
127       char buf[512];
128       if (mapEntry.pr_pathoff) {
129          pread(map_fd, buf, 512, mapEntry.pr_pathoff);
130       }
131       
132       printf("%lu\n" 
133              "\taddr = %llx +%llu\n"
134              "\tmapname = %s\n"
135              "\toffset = %llu, flags = %d\n"
136              "\tpr_pathoff = %d (%s)\n"
137              "\tobject = %s\n"
138              "\talias = %llx, gp = %llx\n",
139              iter * sizeof(prmap_t), 
140              mapEntry.pr_vaddr, mapEntry.pr_size, 
141              mapEntry.pr_mapname,
142              mapEntry.pr_off, mapEntry.pr_mflags,
143              mapEntry.pr_pathoff, mapEntry.pr_pathoff ? buf : "NONE",
144              mapEntry.pr_pathoff ? buf + strlen(buf) + 1 : "NONE",
145              mapEntry.pr_alias, mapEntry.pr_gp);
146       if (mapEntry.pr_pathoff) {
147          string filename = buf;
148          string object_name = buf + strlen(buf) + 1;
149          LoadedLib *ll = new LoadedLibAIX(filename, 0, object_name);
150          Symtab *s = ll->getSymtab();
151          printf("\timageOffset = %ld, length = %lu\n"
152                 "\tdataOffset = %ld, length = %lu\n",
153                 s->imageOffset(), s->imageLength(),
154                 s->dataOffset(), s->dataLength());
155       }
156
157       printf("\n");
158       iter++;
159    }
160 #endif
161
162    iter = 0;
163
164    for (;;) {
165       result = pread(map_fd, &mapEntry, sizeof(prmap_t), iter * sizeof(prmap_t));
166       if (result != sizeof(prmap_t))
167          break;
168       if (mapEntry.pr_size == 0)
169          break;
170       
171       string filename;
172       string object_name;
173       /*      
174               if (is_aout) {
175                 char buf[128];
176                 sprintf(buf, "/proc/%d/object/a.out", pid);
177                 filename = deref_link(buf);
178               }
179       */
180       if (mapEntry.pr_pathoff) {
181          char buf[512];
182          pread(map_fd, buf, 256, mapEntry.pr_pathoff);
183          filename = deref_link(buf);
184          object_name = buf + strlen(buf) + 1;
185       }
186       else {
187          filename = deref_link(mapEntry.pr_mapname);
188       }
189               
190       is_aout = false;
191       
192       LoadedLib *ll = new LoadedLibAIX(filename, (unsigned long)mapEntry.pr_vaddr, object_name);
193
194       iter++;
195       ll->add_mapped_region((unsigned long)mapEntry.pr_vaddr, mapEntry.pr_size);
196       libs.push_back(ll);
197
198       prmap_t next;
199       result = pread(map_fd, &next, sizeof(prmap_t), iter * sizeof(prmap_t));
200       if (result != sizeof(prmap_t))
201          break;
202       if (strcmp(mapEntry.pr_mapname, next.pr_mapname))
203          continue;
204
205       iter++;
206       ll->add_mapped_region((unsigned long)next.pr_vaddr, next.pr_size);
207       ll->setDataLoadAddr((unsigned long)next.pr_vaddr);
208    }
209    
210    P_close(map_fd);
211    return true;
212 }
213
214 AddressTranslate *AddressTranslate::createAddressTranslator(PID pid_, 
215                                                             ProcessReader *,
216                                                             SymbolReaderFactory *fact,
217                                                             PROC_HANDLE, 
218                                                             std::string)
219 {
220    AddressTranslate *at = new AddressTranslateAIX(pid_, fact);
221    
222    if (!at) {
223       return NULL;
224    }
225    else if (at->creation_error) {
226       delete at;
227       return NULL;
228    }
229    return at;
230 }
231
232 AddressTranslate *AddressTranslate::createAddressTranslator(ProcessReader *, SymbolReaderFactory *fact, std::string exename)
233 {
234    return createAddressTranslator(getpid(), NULL, fact);
235 }
236
237 AddressTranslateAIX::AddressTranslateAIX(SymbolReaderFactory *fact)
238    : AddressTranslate(0)
239 {
240    symfactory = fact;
241 }
242    
243 AddressTranslateAIX::AddressTranslateAIX(PID pid, SymbolReaderFactory *fact)
244    : AddressTranslate(pid)
245 {
246    symfactory = fact;
247    refresh();
248 }
249
250 AddressTranslateAIX::~AddressTranslateAIX()
251 {
252 }
253
254 vector< pair<Address, unsigned long> > *LoadedLib::getMappedRegions()
255 {
256    return &mapped_regions;
257 }
258
259 LoadedLibAIX::LoadedLibAIX(string name, Address load_addr, string obj)
260    : LoadedLib(name, load_addr),
261      object(obj),
262      real_codeBase(0),
263      real_dataBase(0),
264      imageOffset(0),
265      dataOffset(0),
266      reals_set(false)
267 {
268 }
269
270 LoadedLibAIX::~LoadedLibAIX()
271 {
272 }
273
274 void LoadedLibAIX::setReals() const
275 {
276    if (reals_set)
277       return;
278
279    SymReader *sreader = symreader_factory->openSymbolReader(name);
280    imageOffset = sreader->imageOffset();
281    dataOffset = sreader->dataOffset();
282    real_codeBase = 0;
283    real_dataBase = 0;
284    /*
285    Symtab *sym = getSymtab();
286    if (!sym)
287       return;
288
289    if (imageOffset > load_addr)
290       real_codeBase = 0;
291    else {
292       real_codeBase = load_addr;
293       if (imageOffset < 0x20000000)
294          real_codeBase -= imageOffset;
295       Region *sec;
296       bool result = sym->findRegion(sec, ".text");
297       if (result && sec)
298          real_codeBase += (Address) sec->getPtrToRawData() - sym->getBaseOffset();
299    }
300
301    if (dataOffset >= data_load_addr)
302       real_dataBase = 0;
303    else if (dataOffset < 0x30000000) {
304       real_dataBase = data_load_addr - dataOffset;
305    }
306    */
307    reals_set = true;
308 }
309
310 Address LoadedLibAIX::offToAddress(Offset off)
311 {
312    setReals();
313    
314    Address addr = off;
315
316    if ((imageOffset < dataOffset && addr >= imageOffset && addr < dataOffset) ||
317        (imageOffset > dataOffset && addr > imageOffset))
318    {
319       return addr + real_codeBase;
320    }
321    else 
322    {
323       return addr + real_dataBase;
324    }
325 }
326
327 Offset LoadedLibAIX::addrToOffset(Address addr)
328 {
329    setReals();
330
331    if (addr >= mapped_regions[0].first && 
332        addr < mapped_regions[0].first + mapped_regions[0].second)
333       return addr - real_codeBase;
334    else
335       return addr - real_dataBase;  
336 }
337
338 Address LoadedLibAIX::getCodeLoadAddr() const
339 {
340    setReals();
341    return real_codeBase;
342 }
343
344 Address LoadedLibAIX::getDataLoadAddr() const
345 {
346    setReals();
347    return real_dataBase;
348 }
349
350 void LoadedLibAIX::getOutputs(string &filename, Address &code, Address &data)
351 {
352    if (object.length())
353       filename = name + ":" + object;
354    else
355       filename = name;
356    code = load_addr;
357    data = data_load_addr;
358 }
359
360 Address AddressTranslateAIX::getLibraryTrapAddrSysV()
361 {
362    return 0x0;
363 }
364
365 }